3 条题解

  • 1
    @ 2024-6-30 13:45:39

    T2:催化剂

    思路

    我们能发现,对于每次查找,若有一种糖果类型的糖果数超过 kk,则它一定会积累最终的答案。

    所以,我们需要将每类糖果先给每个小朋友一个,其余的都给一个小朋友即可。

    这样一来,问题就转变为了计算:

    • aa 为糖果数量大于 kk 的糖果类型的总糖果数量有多少。
    • bb 为糖果数量大于 kk 的糖果类型的糖果数量之和。
    • kk 与题意相同。
    ans=bakans=b-a*k

    解题方法

    我们使用树状数组进行维护,一个负责找到超过 kk 的糖果类型有几个,另一个负责找到超过 kk 的糖果类型的总糖果数量有多少。

    简单的说,一个在变动时只是 +1-1 的变化,另一个则是 +x-x 的变化。

    Code

    #include <bits/stdc++.h> 
    #define ll long long
    using namespace std;
    long long n,m;
    long long c[1000011*6],a;
    ll p[1000011];
    ll cs[1000011*6];
    long long lowbit(long long x){
    	return x&(-x);
    }
    long long getsun(long long x){
    	if(!x) return 0;
    	long long sum=0;
    	for(long long i=x;i;i-=lowbit(i)) sum+=c[i];
    	return sum;
    }
    void update(long long x,long long y){
    	if(!x) return ;
    	for(long long i=x;i<=2300000;i+=lowbit(i)){
    		c[i]+=y;
    	} 
    }
    long long lowbits(long long x){
    	return x&(-x);
    }
    long long getsuns(long long x){
    	if(!x) return 0;
    	long long sum=0;
    	for(long long i=x;i;i-=lowbits(i)) sum+=cs[i];
    	return sum;
    }
    void updates(long long x,long long y){
    	if(!x) return ;
    	for(long long i=x;i<=2300000;i+=lowbits(i)){
    		cs[i]+=y;
    	} 
    }
    // 直接粘贴,懒
    int main(){
    	cin >>n >>m;
    	for(long long i=1;i<=n;i++){
    		ll x;
    		scanf("%lld",&x);
    		updates(p[x]+1,p[x]+1);
    		update(p[x]+1,1);
    		updates(p[x],-p[x]);
    		update(p[x],-1);
    		p[x]++;
    	}
    	while(m--){
    		int op;
    		scanf("%d",&op);
    		if(op==1){
    			long long x;
    			scanf("%lld",&x);
    			update(p[x]+1,1);
    			updates(p[x]+1,p[x]+1);
    			update(p[x],-1);
    			updates(p[x],-p[x]);
    			p[x]++;
    		}else if(op==2){
    			ll x;
    			cin >>x;
    			update(p[x],-1);
    			updates(p[x],-p[x]);
    			update(p[x]-1,1);
    			updates(p[x]-1,p[x]-1);
    			p[x]--;
    		}else{
    			long long x;
    			scanf("%lld",&x);
    			cout <<getsuns(2000000)-getsuns(x)-(getsun(2000000)-getsun(x))*x <<'\n';
    		}
    	}
    	return 0;
    }
    

    信息

    ID
    3
    时间
    1000ms
    内存
    512MiB
    难度
    4
    标签
    递交数
    465
    已通过
    95
    上传者