codeforces 1180E Serge and Dining Room 线段树
Posted mountaink
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces 1180E Serge and Dining Room 线段树相关的知识,希望对你有一定的参考价值。
题目大意:
给出a序列和b序列,a序列为各种食物的价格,b序列为一列排着队的小朋友拥有的钱,小朋友依次购买食物,每个人都买自己能买的起的最贵的食物,买不起就离开队伍。给出q次操作,操作1是修改食物的价格,操作2是修改小朋友的钱,每次操作后询问当小朋友买完之后,能买到的最贵的食物的价格是多少,没有食物了就输出-1.
思路:
首先,小朋友的顺序对最终答案没有任何影响,因为如果两个小朋友能买两个东西,这两个小朋友无论怎么换,都是能买的了的。
其次,对于一个价格为x的物品,如果有一个钱大于等于x的小朋友,就可以买走这个物品。如果我们把价格想象成一条数轴,那么物品就是1,小朋友就是-1,价格或者钱就是坐标轴的位置,这道题就转化成了求最大的后缀和大于等于1的下标。
最后,我们用线段树来维护这个值,注意用线段树维护最大后缀和时,在查询时要注意后面的区间的影响。
#include<bits/stdc++.h> #define clr(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000010; int n,m,q; int sum[maxn<<2],maxx[maxn<<2]; int a[maxn],b[maxn]; void update(int o,int l,int r,int p,int val) if(l==r) sum[o]+=val; maxx[o]+=val; return; int mid=(l+r)>>1; if(p<=mid)update(o<<1,l,mid,p,val); else update(o<<1|1,mid+1,r,p,val); sum[o]=sum[o<<1]+sum[o<<1|1]; maxx[o]=max(maxx[o<<1|1],maxx[o<<1]+sum[o<<1|1]); //这里的每一个maxx,都是对应的 区间最大后缀和 但不是整根数轴的最大后缀和。 struct node int max,sum; ; int query(int o,int l,int r,node tep) if(l==r) return l; int mid=(l+r)>>1; node tep2; tep2.sum=tep.sum+sum[o<<1|1]; tep2.max=maxx[o<<1|1]+tep.sum;//将 标号为o这段区间的后面一段(o+1)的影响合并到o区间中 if(tep2.max>0) return query(o<<1|1,mid+1,r,tep); else return query(o<<1,l,mid,tep2); int main() while(cin>>n>>m) clr(sum,0),clr(maxx,0); for(int i=1;i<=n;i++) scanf("%d",&a[i]); update(1,1,maxn-1,a[i],1); for(int i=1;i<=m;i++) scanf("%d",&b[i]); update(1,1,maxn-1,b[i],-1); cin>>q; while(q--) int op,pos,val; scanf("%d%d%d",&op,&pos,&val); if(op==1) update(1,1,maxn-1,a[pos],-1); update(1,1,maxn-1,a[pos]=val,1); else update(1,1,maxn-1,b[pos],1); update(1,1,maxn-1,b[pos]=val,-1); if(maxx[1]<=0)puts("-1"); else printf("%d\n",query(1,1,maxn-1,0,0));
以上是关于codeforces 1180E Serge and Dining Room 线段树的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #643 (Div. 2)
Codeforces 854 B Maxim Buys an Apartment 思维 水题