题意:给出一个数组a,表示每个菜的价格,给出一个数组b表示每个学生手里拥有的钱,规定在每个学生会选择他能买得起的最贵的菜。现在给出q个询问,询问1将第x个菜的价格改为y,询问2将第x个学生手里的钱改为y,每次询问输出作者能买的最贵的菜的价格。
思路:对于每一道菜,我们都会将区间【1,a[i[】加1,对于每一个学生我们都会将区间【1,b[i]】减1,这个的话查找一下那个点的值大于0就说明这个菜还没人买走,我们只要选择最右边的的大于0的位置就行。由于作者要选还没被买走的最贵的菜,所以线段树查询query的时候要稍微改一下,我们尽量选择右区间
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+1;
int a[maxn],b[maxn],n,m,q;
struct node{
int l,r,maxx,lazy;
}tree[maxn<<2];
void pushup(int x)
{
tree[x].maxx=max(tree[x<<1].maxx,tree[x<<1|1].maxx);
}
void pushdown(int x)
{
if(tree[x].lazy)
{
tree[x<<1].lazy+=tree[x].lazy;
tree[x<<1|1].lazy+=tree[x].lazy;
tree[x<<1].maxx+=tree[x].lazy;
tree[x<<1|1].maxx+=tree[x].lazy;
tree[x].lazy=0;
}
}
void build(int x,int l,int r)
{
tree[x].l=l;tree[x].r=r;tree[x].lazy=0;
if(l==r){
tree[x].maxx=0;
return ;
}
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
pushup(x);
}
void update(int x,int l,int r,int v)
{
if(l<=tree[x].l&&tree[x].r<=r)
{
tree[x].lazy+=v;
tree[x].maxx+=v;
return ;
}
pushdown(x);
int mid=(tree[x].l+tree[x].r)>>1;
if(l<=mid) update(x<<1,l,r,v);
if(mid<r) update(x<<1|1,l,r,v);
pushup(x);
}
int query(int x)
{
if(tree[x].l==tree[x].r)
{
return tree[x].l;
}
pushdown(x);
int mid=(tree[x].l+tree[x].r)>>1;
if(tree[x<<1|1].maxx>0) return query(x<<1|1);
return query(x<<1);
}
int main()
{
scanf("%d %d",&n,&m);
build(1,1,maxn);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]),update(1,1,a[i],1);
for(int i=1;i<=m;++i)
scanf("%d",&b[i]),update(1,1,b[i],-1);
scanf("%d",&q);
while(q--)
{
int op,x,y;
scanf("%d %d %d",&op,&x,&y);
if(op==1)
{
update(1,1,a[x],-1);//要把原来的改回来
a[x]=y;
update(1,1,a[x],1);//再加新的加进来
}
else {
update(1,1,b[x],1);//要把原来的改回来
b[x]=y;
update(1,1,b[x],-1);//再加新的加进来
}
if(tree[1].maxx<=0) puts("-1");
else printf("%d\n",query(1));
}
}