1 条题解
-
0
考虑什么样的区间是合法的。
题目很二分图。不妨将 看成左部点, 看成右部点。每次询问的区间 中,对于所有 , 向所有满足 的 连边,答案等价于是否有完美匹配。
将 与 放在一起从小到大排序,若最后排出来的形式为 必然无解。每个 对一个前缀里的所有 连边然后删掉边 。根据 hall 定理,这 个 与 的邻集大小为 ,则不存在完美匹配。
发现好像构造不出来其他的无解形式了,尝试归纳上述情况:存在 满足 相邻且 之前的 与 数量相等。
由于 ,则排序之后的形式必然是一个合法的括号匹配,不考虑删边,始终有 ( 为 的邻集);删除 后,有 ,当且仅当在上述情况时取等。
有了结论后,实现是简单的。
将第 个学生看成区间 ,结论等价于存在一个区间与其他区间的交集为空。预处理 分别表示 左边最近的与 有交的区间, 右边最近的与 有交的区间(不存在则分别为极小/极大值),合法要求 。
求 是区间覆盖求极值,判合法可以离线扫描线,时间复杂度 。
#include<bits/stdc++.h> #define lt id<<1 #define rt id<<1|1 #define fi first #define se second #define mk make_pair #define pi pair<int,int> using namespace std; const int N=5e5+10,M=N<<1,K=M<<2; inline int read() { int x=0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); return x; } int n,q,a[N],b[N],L[N],R[N],Mx[K]; bool ans[N]; pi num[K],tag[K]; vector<pi>ask[M]; vector<int>ned[M]; inline void Max(int &x,int y) {x=x>y?x:y;} void build(int id,int l,int r) { num[id]=mk(0,1e9); if(l==r) return; int mid=(l+r)>>1; build(lt,l,mid); build(rt,mid+1,r); } void push_up(int id) {num[id]=max(num[lt],num[rt]);} void push_down(int id) { if(!tag[id].fi) return; num[lt]=num[rt]=tag[lt]=tag[rt]=tag[id]; tag[id].fi=0; } void add(int id,int l,int r,int L,int R,int T,int x) { if(l>R||r<L) return; if(L<=l&&r<=R) return num[id]=tag[id]=mk(T,x),void(); push_down(id); int mid=(l+r)>>1; add(lt,l,mid,L,R,T,x); add(rt,mid+1,r,L,R,T,x); push_up(id); } pi query(int id,int l,int r,int L,int R) { if(l>R||r<L) return mk(0,0); if(L<=l&&r<=R) return num[id]; push_down(id); int mid=(l+r)>>1; return max(query(lt,l,mid,L,R),query(rt,mid+1,r,L,R)); } void Push_up(int id) {Mx[id]=max(Mx[lt],Mx[rt]);} void Build(int id,int l,int r) { if(l==r) return Mx[id]=R[l],void(); int mid=(l+r)>>1; Build(lt,l,mid); Build(rt,mid+1,r); Push_up(id); } void Del(int id,int l,int r,int x) { if(l==r) return Mx[id]=0,void(); int mid=(l+r)>>1; x<=mid?Del(lt,l,mid,x):Del(rt,mid+1,r,x); Push_up(id); } int Query(int id,int l,int r,int L,int R) { if(l>R||r<L) return 0; if(L<=l&&r<=R) return Mx[id]; int mid=(l+r)>>1; return max(Query(lt,l,mid,L,R),Query(rt,mid+1,r,L,R)); } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); n=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) b[i]=read(); for(int i=1;i<=n;i++) L[i]=query(1,1,n+n,b[i],a[i]).se,add(1,1,n+n,b[i],a[i],i,i); build(1,1,n+n); for(int i=n;i;i--) R[i]=query(1,1,n+n,b[i],a[i]).se,add(1,1,n+n,b[i],a[i],n-i+1,i); for(int i=1;i<=n;i++) ned[L[i]].push_back(i); Build(1,1,n); q=read(); for(int i=1,l,r;i<=q;i++) l=read(),r=read(),ask[l].push_back(mk(r,i)); for(int i=n;i;i--) { for(int x:ned[i]) Del(1,1,n,x); for(pi x:ask[i]) ans[x.se]=Query(1,1,n,i,x.fi)<=x.fi; } for(int i=1;i<=q;i++) puts(ans[i]?"Yes":"No"); return 0; }
- 1
信息
- ID
- 9058
- 时间
- 2500ms
- 内存
- 1024MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者