牛客网暑期ACM多校第六场I - 线段树

题目链接:点击这里

解题思路:

这题还不让离线真的是,不过它把关键放在了删除上面,这就是一个区间被覆盖之后就会被删除了。那么这个问题就可以用O(nlogn)来解决了.用左端点l来离散建立线段树,右端点r作为区间值。线段树维护区间最大值.

那么我们去查询x的时候实际上就是在线段树[1,x]中去查找值不小于x的点,然后把它删除,之后改变他的值为负无穷,因为他已经被删除了。这就是为什么可以用O(nlogn)来解决。那么要是区间最大值小于x,这个区间就不同区看了,一定没有满足条件的。

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define mp(a,b) make_pair(a,b)
using namespace std;
const int mx = 2e5 + 10;
const int mod = 998244353;
typedef long long ll;
int n,m,pos[mx<<2],big[mx<<2];
int cnt,ret,ans[mx],res;
struct node
{
	int l,r;
	int p;
	bool operator < (node A)const
	{
		return l < A.l;
	}
}s[mx];
void build(int l,int r,int rt)
{
	if(l==r){
		big[rt] = s[l].r;
		pos[rt] = s[l].p;
        ans[l] = 0;
		return ;
	}
	int mid = (l+r)>>1;
	build(lson);
	build(rson);
	big[rt] = max(big[rt<<1],big[rt<<1|1]); 
}
void update(int R,int v,int l,int r,int rt)
{
	if(big[rt]<v) return ;
	if(l==r){
		++cnt;
		big[rt] = -inf;
		res = (1ll*res*pos[rt])%mod;
		ans[pos[rt]] = ret;
		return ;
	}
	int mid = (l+r)>>1;
	update(R,v,lson);
	if(R>mid) update(R,v,rson);
	big[rt] = max(big[rt<<1],big[rt<<1|1]); 	
}
int main()
{
	int t,cas =1;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++){
			scanf("%d%d",&s[i].l,&s[i].r);
			s[i].p = i;
		}
		sort(s+1,s+1+n);
		build(1,n,1);
		int y;res = 0;
		printf("Case #%d:\n",cas++);
		for(int i=1;i<=m;i++){
			scanf("%d",&y);
			y = (y^res);
			cnt = 0,ret = i,res = 1;
			int R = upper_bound(s+1,s+1+n,(node){y,0,0}) - s - 1;
			if(R) update(R,y,1,n,1);
			if(!cnt) res = 0;
			printf("%d\n",cnt);
		}
		for(int i=1;i<=n;i++) printf("%d%c",ans[i],i==n?'\n':' ');
	}
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a1214034447/article/details/81416568