题意:
有n个菜,m个人,这m个人排队买菜。每个菜有一个价格a1-an,每个人都有一些钱b1-bm。每个人在自己钱足够的情况下会购买最贵的菜,如果一个菜都买不起就不买。Serge排在队伍的最后(不包括在m个人中),求他最后可以买的最贵的菜。
有两个操作:
1 x y: 把第x个菜的价格变为y
2 x y: 把第x个人的钱变为y
操作是累积的
思路:
把所有出现过的价格全部离散化,以价格为权值建一棵权值线段树。若有一个菜的价格为x,更新权值(1,x)的区间全部加1,若有一个人的钱是x,则更新权值(1,x)的区间全部减1。这样的意义在于当一个价格x的值为正时表示这个菜不能被人买走,而为负时,则表示被人买走。
参考代码:
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
const int R=N*2;
int a[N],b[N],ls[N<<2],op[N],dx[N],dy[N];
int top=0;
#define lson rt<<1
#define rson rt<<1|1
int tree[R<<2],lazy[R<<2];
void pushdown(int rt){
tree[lson]+=lazy[rt];
tree[rson]+=lazy[rt];
lazy[lson]+=lazy[rt];
lazy[rson]+=lazy[rt];
lazy[rt]=0;
}
void update(int rt,int l,int r,int x,int y,int k){
if(l>=x&&r<=y){
tree[rt]+=k;
lazy[rt]+=k;
return;
}
int mid=(l+r)>>1;
pushdown(rt);
if(y<=mid)update(lson,l,mid,x,y,k);
else if(x>mid)update(rson,mid+1,r,x,y,k);
else update(lson,l,mid,x,mid,k),update(rson,mid+1,r,mid+1,y,k);
tree[rt]=max(tree[lson],tree[rson]);
}
int query(int rt,int l,int r){//能往右找就往右找,找到最大的
if(l==r){
return l;
}
int mid=(l+r)>>1;
pushdown(rt);
if(tree[rson]>0){
return query(rson,mid+1,r);
}
else{
return query(lson,l,mid);
}
}
void add1(int x){
update(1,1,R,1,x,1);
}
void del1(int x){
update(1,1,R,1,x,-1);
}
void add2(int x){
update(1,1,R,1,x,-1);
}
void del2(int x){
update(1,1,R,1,x,1);
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
ls[++top]=a[i];
}
for(int i=1;i<=m;i++){
scanf("%d",&b[i]);
ls[++top]=b[i];
}
int q;
scanf("%d",&q);
for(int i=1;i<=q;i++){
scanf("%d%d%d",&op[i],&dx[i],&dy[i]);
op[i]--;
ls[++top]=dy[i];
}
//预处理离散化
sort(ls+1,ls+1+top);
top=unique(ls+1,ls+1+top)-ls-1;
for(int i=1;i<=n;i++){
a[i]=lower_bound(ls+1,ls+1+top,a[i])-ls;
}
for(int i=1;i<=m;i++){
b[i]=lower_bound(ls+1,ls+1+top,b[i])-ls;
}
for(int i=1;i<=q;i++){
dy[i]=lower_bound(ls+1,ls+1+top,dy[i])-ls;
}
//建树
for(int i=1;i<=n;i++){
add1(a[i]);
}
for(int i=1;i<=m;i++){
add2(b[i]);
}
for(int i=1;i<=q;i++){
if(!op[i]){
del1(a[dx[i]]);
a[dx[i]]=dy[i];
add1(a[dx[i]]);
}
else{
del2(b[dx[i]]);
b[dx[i]]=dy[i];
add2(b[dx[i]]);
}
if(tree[1]<1){//若根为正,至少有一个叶子节点的值为正
printf("-1\n");
}
else{
int ret=query(1,1,R);
printf("%d\n",ls[ret]);
}
}
return 0;
}