[CF1098D] Eels

[题目链接]

http://codeforces.com/contest/1098/problem/D

[题解]

首先 , 记满足 (sum_{i = 1}^{i - 1}{a_{j}} > 2 * a_{i})(i) 的个数为 (S)

不难发现答案的上界是 ((N - S))

考虑如何取到这个上界 , 不妨每次取出最小的两个元素 (a)(b) , 将 (a) , (b) 分别删除 , 再将 ((a + b)) 插入集合。

如果 (a , b) 合并操作不是 "危险" 的 , 那么必然满足 (b) 没有被合并过。因为如果 (b) 被合并过 , 令 (b = c + d) ((c geq d)) , 那么 (d geq frac{b}{2} > a) , 故 (d) 必然被合并过 , 矛盾。

那么对 ([2^0,2^1),[2^1,2^2),[2^2,2^3),cdots,[2^{29},2^{30})) 分别维护区间和及 (multiset) 即可。

时间复杂度 : (O(NlogN))

[代码]

#include<bits/stdc++.h>
 
using namespace std;
 
typedef long long LL;
 
#define rep(i , l , r) for (int i = (l); i < (r); ++i)
 
LL q , ans , sum[60];
multiset < LL > s[60];
char ch[60];
 
int main() {
	 
	 int q; scanf("%d" , &q);
	 while (q--) {
	 	 LL x , bit = 0;
	 	 scanf("%s%lld" , ch , &x);
	 	 for (bit = 1; (1 << bit) <= x; ++bit); --bit;
	 	 if (ch[0] == '+') {
	 	 	 sum[bit] += x;
			 s[bit].insert(x);	 
		 } else {
		 	 sum[bit] -= x;
		 	 s[bit].erase(s[bit].find(x));
		 }
		 LL siz = 0 , ans = 0;
		 for (int i = 0; i < 30; ++i) {
		 	 if (!s[i].size()) continue;
		 	 ans += (s[i].size() - ((*s[i].begin()) > 2 * siz));
		 	 siz += sum[i];
		 }
		 printf("%lld
" , ans);
	 } 
     return 0;
}
原文地址:https://www.cnblogs.com/evenbao/p/14468970.html