codeforces1098D Eels

題面

題意

在魚缸中有一些魚,這些魚之間會相互吞噬直到只剩下一條魚,若一條魚的質量爲a,另一條魚的質量爲b,則吞噬之後會剩下一條質量爲a+b的魚,若a<=ba<=bb<=2ab<=2*a,則這次吞噬是危險的。
現在有一個空魚缸,進行多次操作,每次操作會加入一條魚或去掉某一條魚,問這次操作後,魚缸中的魚相互吞噬直到只剩下一條魚,至多有幾次是危險的。

做法

首先考慮怎樣吞噬纔會使危險次數最多,可以發現如果每次挑選最輕的兩條魚互吞,答案最大,進一步可以發現,對所有魚按質量進行排序後,若一條魚與其他魚合併會對答案造成貢獻,當且僅當wi<=2j<iwjw_i<=2*\sum_{j<i}{w_j}
現在考慮維護這個東西。
根據魚的質量將其分爲30個區間:[1,2),[2,4),[4,8)......[229,230)[1,2),[2,4),[4,8)......[2^{29},2^{30})
然後可以發現,如果一個區間中有多個元素,則只有最小的元素可能不是危險的,因此我們只要維護每個區間的和,每次詢問O(30)O(30)暴力計算即可

代碼

#include<bits/stdc++.h>
#define ll long long
using namespace std;

ll Q,ans,sum[40];
char str[2];
multiset<ll>num[40];

int main()
{
    ll i,j,t,qz;
    cin>>Q;
    while(Q--)
    {
	scanf("%s%lld",str,&t);
	for(i=1;(1 << i)<=t;i++);i--;
	if(str[0]=='+')
	{
	    sum[i]+=t;
	    num[i].insert(t);
	}
	else
	{
	    sum[i]-=t;
	    num[i].erase(num[i].find(t));
	}
	qz=ans=0;
	for(i=0;i<30;i++)
	{
	    if(!num[i].size()) continue;
	    ans+=(num[i].size()-((*num[i].begin())>2*qz));
	    qz+=sum[i];
	}
	printf("%lld\n",ans);
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章