金鱼草
有 \(m\) 个区间,求是否存在某些区间的并集是否等于查询区间?
\(1\leq l,r\leq n\leq 5\times 10^5\),\(1\leq m,q\leq 5\times 10^5\)。
思路
对于一个查询 \([l',r']\) 而言,可能对其产生贡献的区间满足 \([l,r]\subseteq [l',r']\)。
一个简单的想法是,查询区间与集合区间按 \(r\) 升序排序,集合区间对 \([l,r]\) 做 \(\max(a_i,l)\),\(a_i\) 表示的就是覆盖 \(i\) 的 \(l\) 最大的区间;查询时查 \([l',r']\) 中的最小 \(a_i\)。如果 \(a_i\) 小于 \(l'\),证明有一个点只能选择 \(l<l'\) 的区间覆盖,不满足要求。否则都是可行的。
线段树维护,复杂度 \(O(n\log n)\)。
CODE
#include<bits/stdc++.h>
using namespace std;#define pii pair<int,int>
#define fi first
#define se secondconst int maxn=5e5+5;int n,m,q;
int l[maxn],r[maxn],ans[maxn];vector<int>chg[maxn],qry[maxn];namespace linetree
{#define lch(p) p*2#define rch(p) p*2+1struct treenode{pii mi;int tagmi;}tr[maxn*4];inline void change(int p,int l,int r,int lx,int rx,int val);inline void pushup(int p){tr[p].mi={1e9,1e9};tr[p].mi.fi=min(tr[lch(p)].mi.fi,tr[rch(p)].mi.fi);if(tr[lch(p)].mi.fi!=tr[p].mi.fi) tr[p].mi.se=min(tr[p].mi.se,tr[lch(p)].mi.fi);if(tr[lch(p)].mi.se!=tr[p].mi.se) tr[p].mi.se=min(tr[p].mi.se,tr[lch(p)].mi.se);if(tr[rch(p)].mi.fi!=tr[p].mi.fi) tr[p].mi.se=min(tr[p].mi.se,tr[rch(p)].mi.fi);if(tr[rch(p)].mi.fi!=tr[p].mi.se) tr[p].mi.se=min(tr[p].mi.se,tr[rch(p)].mi.se);}inline void pushdown(int p,int l,int r){int mid=(l+r)>>1;if(tr[p].tagmi==0) return ;change(lch(p),l,mid,l,mid,tr[p].tagmi);change(rch(p),mid+1,r,mid+1,r,tr[p].tagmi);tr[p].tagmi=0;}inline void build(int p,int l,int r){if(l==r){tr[p].mi.fi=0;tr[p].mi.se=1e9;return ;}int mid=(l+r)>>1;build(lch(p),l,mid),build(rch(p),mid+1,r);pushup(p);}inline void change(int p,int l,int r,int lx,int rx,int val){if(r<lx||l>rx||tr[p].mi.fi>=val) return ;if(lx<=l&&r<=rx){if(tr[p].mi.fi<val&&val<tr[p].mi.se){tr[p].mi.fi=val;tr[p].tagmi=val;return ;}}pushdown(p,l,r);int mid=(l+r)>>1;change(lch(p),l,mid,lx,rx,val),change(rch(p),mid+1,r,lx,rx,val);pushup(p);}inline int qry(int p,int l,int r,int lx,int rx){if(r<lx||l>rx) return 1e9;if(lx<=l&&r<=rx) return tr[p].mi.fi;pushdown(p,l,r);int mid=(l+r)>>1;return min(qry(lch(p),l,mid,lx,rx),qry(rch(p),mid+1,r,lx,rx));}#undef lch#undef rch
}int main()
{freopen("snapdragon.in","r",stdin);freopen("snapdragon.out","w",stdout);scanf("%d%d%d",&n,&m,&q);for(int i=1;i<=m;i++){int l,r;scanf("%d%d",&l,&r);chg[r].emplace_back(l);}for(int i=1;i<=q;i++){scanf("%d%d",&l[i],&r[i]);qry[r[i]].emplace_back(i);}linetree::build(1,1,n);for(int i=1;i<=n;i++){for(auto l:chg[i])linetree::change(1,1,n,l,i,l);for(auto k:qry[i])ans[k]=linetree::qry(1,1,n,l[k],r[k]);}for(int i=1;i<=q;i++){// cerr<<ans[i]<<"\n";puts(ans[i]>=l[i]?"YES":"NO");}
}