cf1284D——线段树,排序
Posted zsben991126
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cf1284D——线段树,排序相关的知识,希望对你有一定的参考价值。
/* 原问题可以简化成:给定n对区间[sai,eai],[sbi,ebi], 是否存在i,j,使[sai,eai],[saj,eaj] 与[sbi,ebi],[sbj,ebj]有且仅有一组相交 思路:遍历第i对区间,先找到a部分和[sai,eai]相交的所有段,设这个段的集合为S, 由于题意,S中所有b部分的段都要和[sbi,ebi]相交,这就要求S中最小的ebj>=sbi,最大的sbj<=ebi 所以想到一开始就对所有的段,按照eai升序排序,然后二分找到[x,i-1]的段a部分和i的a部分相交, 再用线段树查询b部分两端的极值,和bi进行比较即可 最后swap一下ab再算一次就好 */ #include<bits/stdc++.h> #define N 200005 using namespace std; struct Seg{int sa,ea,sb,eb;}p[N]; int cmp(Seg &a,Seg &b){ if(a.ea!=b.ea)return a.ea<b.ea; else return a.sa<b.sa; } int n,mx[4*N], mi[4*N]; void creat(int l, int r, int k) { if(l == r){ mx[k]=p[l].sb, mi[k]=p[l].eb; return ; } int mid = (l+r)/2; creat(l, mid, 2*k); creat(mid+1, r, 2*k+1); mx[k] = max(mx[2*k], mx[2*k+1]); mi[k] = min(mi[2*k], mi[2*k+1]); } int querymin(int l, int r, int al, int ar, int k) { if(l == al && r == ar)return mi[k]; int mid = (l+r)/2; if(ar <= mid)return querymin(l, mid, al, ar, 2*k); else if(al > mid)return querymin(mid+1, r, al, ar, 2*k+1); else return min(querymin(l, mid, al, mid, 2*k), querymin(mid+1, r, mid+1, ar, 2*k+1)); } int querymax(int l, int r, int al, int ar, int k) { if(l == al && r == ar)return mx[k]; int mid = (l+r)/2; if(ar <= mid)return querymax(l, mid, al, ar, 2*k); else if(al > mid)return querymax(mid+1, r, al, ar, 2*k+1); else return max(querymax(l, mid, al, mid, 2*k), querymax(mid+1, r, mid+1, ar, 2*k+1)); } int ea[N]; int solve(){ std::sort(p+1,p+1+n,cmp); creat(1,n,1); for(int i=1;i<=n;i++)ea[i]=p[i].ea; for(int i=1;i<=n;i++){ if(i==1)continue; int left = p[i].sa; //二分找到 int ans=lower_bound(ea+1,ea+i,left)-ea; if(ans>i-1)continue; //判断b部分是否合法 int maxL=querymax(1,n,ans,i-1,1); int minR=querymin(1,n,ans,i-1,1); if(minR<p[i].sb || maxL>p[i].eb) return 0; } return 1; } int main(){ /* cin>>n; for(int i=1;i<=n;i++) cin>>p[i].sa>>p[i].ea>>p[i].sb>>p[i].eb; int res=solve(); for(int i=1;i<=n;i++) swap(p[i].sa,p[i].sb),swap(p[i].ea,p[i].eb); res &= solve(); if(res)puts("YES"); else puts("NO"); */ int i, j, k, sig = 1; scanf("%d", &n); for(i=1;i<=n;i++) scanf("%d %d %d %d", &p[i].sa, &p[i].ea, &p[i].sb, &p[i].eb); sig &= solve(); for(i=1;i<=n;i++) swap(p[i].sa, p[i].sb), swap(p[i].ea, p[i].eb); sig &= solve(); if(sig)printf("YES "); else printf("NO "); }
以上是关于cf1284D——线段树,排序的主要内容,如果未能解决你的问题,请参考以下文章