Codeforces Round #569 (Div. 2) E - Serge and Dining Room(线段树+思维)

在这里插入图片描述
在这里插入图片描述
题意:给出一个数组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));
	}
} 
发布了39 篇原创文章 · 获赞 0 · 访问量 1070

猜你喜欢

转载自blog.csdn.net/qq_42479630/article/details/104063421