[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\n" , ans);
	 } 
     return 0;
}
posted @ 2021-03-02 14:57  evenbao  阅读(79)  评论(0编辑  收藏  举报