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; }