https://codeforces.com/contest/1180/problem/E
转载自他人博客
题意:
有nn个菜肴,有mm个小朋友,每个菜肴的价格为aiai,每个小朋友有bibi元钱,小朋友从1→m1→m依次购买菜肴,当第ii个小朋友轮到的时候,他会购买他买的起的最贵的,否则就离开。
要求支持修改第ii个菜肴的价格和修改第ii个小朋友的拥有的钱数的两种操作,每次操作完成给出mm个小朋友买完后剩下的最贵的菜肴的价格是多少。
思路:
假设价格大于xx的yy个菜肴都被买了,那么显然拥有钱数≥x≥x的小朋友个数一定要≥y≥y,显然如何购买是无所谓的。
那么就在aiai处减一,bibi处加一,每次询问一个最大的ll使得[l,∞][l,∞]的最大后缀和>0>0。
线段树维护即可。
代码:
1 #include<bits/stdc++.h> 2 #define clr(a,b) memset(a,b,sizeof(a)) 3 using namespace std; 4 typedef long long ll; 5 const int maxn=1000010; 6 int n,m,q; 7 int sum[maxn<<2],maxx[maxn<<2]; 8 int a[maxn],b[maxn]; 9 void update(int o,int l,int r,int p,int val){ 10 if(l==r){ 11 sum[o]+=val; 12 maxx[o]+=val; 13 return; 14 } 15 int mid=(l+r)>>1; 16 if(p<=mid)update(o<<1,l,mid,p,val); 17 else update(o<<1|1,mid+1,r,p,val); 18 sum[o]=sum[o<<1]+sum[o<<1|1]; 19 maxx[o]=max(maxx[o<<1|1],maxx[o<<1]+sum[o<<1|1]); 20 //这里的每一个maxx,都是对应的 区间最大后缀和 但不是整根数轴的最大后缀和。 21 } 22 struct node{ 23 int max,sum; 24 }; 25 int query(int o,int l,int r,node tep){ 26 if(l==r){ 27 return l; 28 } 29 int mid=(l+r)>>1; 30 node tep2; 31 tep2.sum=tep.sum+sum[o<<1|1]; 32 tep2.max=maxx[o<<1|1]+tep.sum;//将标号为o这段区间的后面一段(o+1)的影响合并到o区间中 33 if(tep2.max>0){ 34 return query(o<<1|1,mid+1,r,tep); 35 } 36 else{ 37 return query(o<<1,l,mid,tep2); 38 } 39 } 40 int main(){ 41 while(cin>>n>>m){ 42 clr(sum,0),clr(maxx,0); 43 for(int i=1;i<=n;i++){ 44 scanf("%d",&a[i]); 45 update(1,1,maxn-1,a[i],1); 46 } 47 for(int i=1;i<=m;i++){ 48 scanf("%d",&b[i]); 49 update(1,1,maxn-1,b[i],-1); 50 } 51 cin>>q; 52 while(q--){ 53 int op,pos,val; 54 scanf("%d%d%d",&op,&pos,&val); 55 if(op==1){ 56 update(1,1,maxn-1,a[pos],-1); 57 update(1,1,maxn-1,a[pos]=val,1); 58 }else{ 59 update(1,1,maxn-1,b[pos],1); 60 update(1,1,maxn-1,b[pos]=val,-1); 61 } 62 if(maxx[1]<=0)puts("-1"); 63 else printf("%d\n",query(1,1,maxn-1,{0,0})); 64 } 65 } 66 }