• [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;
    }
    
  • 相关阅读:
    第二阶段冲刺7
    第二阶段冲刺6
    课后作业02需求分析
    阅读计划
    个人总结
    第十六周学习进度条
    第十五周学习进度条
    《梦断代码》阅读笔记03
    《梦断代码》阅读笔记02
    《梦断代码》阅读笔记01
  • 原文地址:https://www.cnblogs.com/evenbao/p/14468970.html
Copyright © 2020-2023  润新知