1080F.Katya and Segments Sets (可持久化线段树+很精妙的思路)

题意:

给出n个区间,每个区间有颜色。

m次询问,每次询问:这n个区间中所有被包含在[x,y]这一区间中的区间,它们的颜色是否取遍了[l,r]中的所有颜色。

题解:

先对所有线段的左右端点离散化。将所有线段按左端点排序。

然后对每个左端点x建一颗线段树。

线段树的下标是颜色,值为该颜色左端点大于等于x时的右端点最小值。

线段树维护区间最大值。

每次查询对应版本的区间颜色最大值。

然后从右往左更新线段树,后来的线段树可以直接继承前面线段树的答案。

查询的时候,先二分出x在离散化数组里的位置,查询最大值是否小于等于y即可。

时间复杂度\(O(nlogn)\)

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+100;
const int M=maxn*40;

struct qnode {
	int l,r;
	int color;
	bool operator < (const qnode &r) const {
		return l<r.l;
	} 
}a[maxn];
int n,m,k;

int t[maxn];
int c[M];
int lson[M];
int rson[M];
int T[maxn];
int tot;
int build (int l,int r) {
	int root=tot++;
	c[root]=2e9;
	if (l!=r) {
		int mid=(l+r)>>1;
		lson[root]=build(l,mid);
		rson[root]=build(mid+1,r);
	}
	return root;
}
int up (int root,int l,int r,int p,int v) {
	int newRoot=tot++;
	if (l==p&&r==p) {
		c[newRoot]=min(c[root],v);
		return newRoot;
	}
	int mid=(l+r)>>1; 
	if (p<=mid) {
		lson[newRoot]=up(lson[root],l,mid,p,v);
		rson[newRoot]=rson[root];
	} 
	if (p>mid) {
		rson[newRoot]=up(rson[root],mid+1,r,p,v);
		lson[newRoot]=lson[root];
	}
	c[newRoot]=max(c[lson[newRoot]],c[rson[newRoot]]);
	return newRoot;
}
int query (int root,int l,int r,int L,int R) {
	if (l>=L&&r<=R) return c[root];
	int mid=(l+r)>>1;
	int ans=0;
	if (L<=mid) ans=max(ans,query(lson[root],l,mid,L,R));
	if (R>mid) ans=max(ans,query(rson[root],mid+1,r,L,R));
	return ans; 
}

int main () {
	scanf("%d%d%d",&n,&m,&k);
	for (int i=1;i<=k;i++) scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].color);
	sort(a+1,a+k+1);
	T[k+1]=build(1,n);
	for (int i=k;i>=1;i--) {
		//int tt=query(T[i+1],1,n,a[i].color,a[i].color);
		T[i]=up(T[i+1],1,n,a[i].color,a[i].r);
	}
	while (m--) {
		int aa,bb,x,y;
		scanf("%d%d%d%d",&aa,&bb,&x,&y);
		int l=1,r=k,p=-1;
		while (l<=r) {
			int mid=(l+r)>>1;
			if (a[mid].l>=x) {
				p=mid;
				r=mid-1;
			}
			else {
				l=mid+1;
			}
		}
		if (p==-1) {
			printf("no\n"),fflush(stdout);
			continue;
		}
		int tt=query(T[p],1,n,aa,bb);
		if (tt<=y)
			printf("yes\n"),fflush(stdout);
		else
			printf("no\n"),fflush(stdout);
	}
} 
posted @ 2021-04-07 11:37  zlc0405  阅读(49)  评论(0编辑  收藏  举报