• 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
    "),fflush(stdout);
    			continue;
    		}
    		int tt=query(T[p],1,n,aa,bb);
    		if (tt<=y)
    			printf("yes
    "),fflush(stdout);
    		else
    			printf("no
    "),fflush(stdout);
    	}
    }
  • 相关阅读:
    深入理解HTTP Session
    java中使用队列:java.util.Queue
    throws/throw Exception 异常应用
    Log4j实现对Java日志的配置全攻略
    java中volatile关键字的含义
    hibernate调用oracle存储过程||函数
    手势仿QQ侧滑---秀清
    归档和解档---秀清
    全局定义UINavigationContoller--By秀清
    重力感应 加速计- By严焕培
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/14627005.html
Copyright © 2020-2023  润新知