cf1080F. Katya and Segments Sets
阿新 • • 發佈:2018-11-27
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; }