AT_abc287_g [ABC287G] Balance Update Query 题解

分析

一眼分块。

用值域分块来维护。先把所有的值离散化,使得至于不大于 \(n+q\)。统计一下每个值的数量,每个块包含值的数量,每个块的价值和。修改值的时候先把原来值的数量,块包含的数量,块的价值剪掉被修改值的贡献,然后在新的值上面更新。修改数量直接改数量的变化贡献即可。

找前 \(x\) 大的值之和从值域上限开始枚举,照常暴力散区间、整块。

复杂度 \(O(q \sqrt{V})\)

注:离散化之后注意贡献是离散化之前的值,要还原。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define re register
#define il inline

const int N=2e5+10;
int n,q;
int a[N],b[N];
struct node{
	int op,x,y;
}Q[N];
int cnt[N<<1],sum[N],val[N],len;
int y[N<<1],c[N<<1],idx;

il int get(int x){return (x-1)/len+1;}
il int query(int x){
	int bl=get(1),br=get(idx);
	int ans=0;
	if(bl==br){
		for(re int i=idx;i>=1;--i){
			if(x<=cnt[i]){ans+=x*y[i];return ans;}
			else{ans+=cnt[i]*y[i],x-=cnt[i];}
		}
		if(x==0) return ans;
		return -1;
	}
	for(re int i=idx;i>=(br-1)*len+1;--i){
		if(x<=cnt[i]){ans+=x*y[i];return ans;}
		else{ans+=cnt[i]*y[i],x-=cnt[i];}
	}
	for(re int bk=br-1;bk>=bl+1;--bk){
		if(x<=sum[bk]){
			for(re int i=bk*len;i>=(bk-1)*len+1;--i){
				if(x<=cnt[i]){ans+=x*y[i];return ans;}
				else{ans+=cnt[i]*y[i],x-=cnt[i];}
			}
			return -1;
		}
		else{ans+=val[bk],x-=sum[bk];}
	}
	for(re int i=bl*len;i>=1;--i){
		if(x<=cnt[i]){ans+=x*y[i];return ans;}
		else{ans+=cnt[i]*y[i],x-=cnt[i];}
	}
	if(x==0) return ans;
	return -1;
}
il void read(){
	cin>>n;
	for(re int i=1;i<=n;++i) cin>>a[i]>>b[i],c[++idx]=a[i];
	cin>>q;
	for(re int i=1;i<=q;++i){
		cin>>Q[i].op;
		if(Q[i].op==3) cin>>Q[i].x;
		else cin>>Q[i].x>>Q[i].y;
		if(Q[i].op==1) c[++idx]=Q[i].y;
	}
	sort(c+1,c+idx+1),idx=unique(c+1,c+idx+1)-(c+1);
	for(re int i=1,x;i<=n;++i) x=a[i],a[i]=lower_bound(c+1,c+idx+1,a[i])-c,y[a[i]]=x;
	for(re int i=1;i<=q;++i){
		if(Q[i].op==1){
			int x=Q[i].y;
			Q[i].y=lower_bound(c+1,c+idx+1,Q[i].y)-c;
			y[Q[i].y]=x;
		}
	}
	return ;
}
il void solve(){
	len=sqrt(idx);
	for(re int i=1;i<=n;++i){
		cnt[a[i]]+=b[i];
		sum[get(a[i])]+=b[i];
		val[get(a[i])]+=b[i]*y[a[i]];
	}
	for(re int i=1;i<=q;++i){
		if(Q[i].op==1){
			cnt[a[Q[i].x]]-=b[Q[i].x];
			sum[get(a[Q[i].x])]-=b[Q[i].x];
			val[get(a[Q[i].x])]-=b[Q[i].x]*y[a[Q[i].x]];
			
			a[Q[i].x]=Q[i].y;
			
			cnt[a[Q[i].x]]+=b[Q[i].x];
			sum[get(a[Q[i].x])]+=b[Q[i].x];
			val[get(a[Q[i].x])]+=b[Q[i].x]*y[a[Q[i].x]];			
		}
		else if(Q[i].op==2){
			cnt[a[Q[i].x]]+=(Q[i].y-b[Q[i].x]);
			sum[get(a[Q[i].x])]+=(Q[i].y-b[Q[i].x]);
			val[get(a[Q[i].x])]+=(Q[i].y-b[Q[i].x])*y[a[Q[i].x]];
			
			b[Q[i].x]=Q[i].y;
		}
		else if(Q[i].op==3){
			cout<<query(Q[i].x)<<"\n";
		}
	}
	return ;
}

signed main(){
	read(),solve();
	return 0;
}
posted @   harmis_yz  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示