1. 程式人生 > >cf1080F. Katya and Segments Sets

cf1080F. Katya and Segments Sets

http://codeforces.com/contest/1080/problem/F

題意  給你n個集合 每個集合都有一定的線段  m次查詢 查詢集合[l,r]內每個集合是否至少有一個線段被[x,y]覆蓋 輸出"yes"或"no";

題解 我們考慮對線段左端點降序排序 用主席維護每個集合對應最小的右端點 然後查詢 集合[l,r]內的最大值是否小於等於y即可

#include<bits/stdc++.h>
const int MAXN=3e5+10;
#define inc(i,l,r) for(int i=l;i<=r;i++)
const int inf=1e9+10;
#define ll long long
#define pb push_back
using namespace std;
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return x*f;
}
typedef struct Q{
	int l,r,pos;
	friend bool operator<(Q aa,Q bb){
		return aa.l>bb.l;
	}
}Q;
Q que[300005];
typedef struct node{
	int l,r,minn;
}node;
node d[MAXN*21];
int rt[MAXN<<2],cnt;
void update(int &x,int y,int l,int r,int p,int t){
	x=++cnt;d[x]=d[y];
	if(l==r){d[x].minn=min(d[x].minn,t);return ;}
	int mid=(l+r)>>1;
	if(p<=mid)update(d[x].l,d[y].l,l,mid,p,t);
	else update(d[x].r,d[y].r,mid+1,r,p,t);
	d[x].minn=max(d[d[x].l].minn,d[d[x].r].minn);
}
int ans;
void querty(int x,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr){ans=max(ans,d[x].minn);return ;}
	int mid=(l+r)>>1;
	if(ql<=mid)querty(d[x].l,l,mid,ql,qr);
	if(qr>mid)querty(d[x].r,mid+1,r,ql,qr);
}
int main(){
	int n,m,k;
	d[0].minn=inf;
	scanf("%d%d%d",&n,&m,&k);
	inc(i,1,k)que[i].l=read(),que[i].r=read(),que[i].pos=read();
	sort(que+1,que+k+1);
	//inc(i,1,k)cout<<que[i].l<<" "<<que[i].r<<" "<<que[i].pos<<endl;
	inc(i,1,k){
		update(rt[i],rt[i-1],1,n,que[i].pos,que[i].r);
	}
	int l,r,x,y;
	while(m--){
		l=read();r=read();x=read();y=read();
		int lx=1;int rx=k;int ans1=0;
		while(lx<=rx){
			int mid=(lx+rx)>>1;
			if(que[mid].l>=x)ans1=mid,lx=mid+1;
			else rx=mid-1;
		}
		bool flag=0;
		if(ans1){
			ans=0;querty(rt[ans1],1,n,l,r);
			if(ans<=y)flag=1;
		}
		if(flag)puts("yes");
		else puts("no");
		fflush(stdout);
	}
	return 0;
}