[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;
}