分析
一眼分塊。
用值域分塊來維護。先把所有的值離散化,使得至於不大於 $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;
}