洛谷P4899/LOJ2865/UOJ407[IOI2018]狼人(kruskal重构树+主席树)
首先如果是边权的话很明显是kruskal重构树了,那么类比,点权也可以用类似的方法搞,只不过把枚举边换成了枚举点
然后建两棵树跑树上倍增就可以得出一个点最多可以到达那些点,我们的目标是判断是否存在一个$u$使得$u$到$S$和$E$均联通。
那么考虑把两颗树的$dfs$序求出来,那么问题就变成了已知两个数列中的各一个区间,求区间是否有交的问题,以$dfn_a$为关键字进行排序,向主席树中插入$dfn_b$,最后用主席树查询即可。
洛谷代码(传统):
#include<cstdio> #include<algorithm> using namespace std; const int N=200050; const int M=800050; char rB[1<<21],*rS,*rT; inline char gc(){return rS==rT&&(rT=(rS=rB)+fread(rB,1,1<<21,stdin),rS==rT)?EOF:*rS++;} inline int rd(){ char c=gc(); while(c<48||c>57)c=gc(); int x=c&15; for(c=gc();c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c&15); return x; } int G[N],to[M],nxt[M],sz1=0,cnt[N<<5],lc[N<<5],rc[N<<5],rt[N],sz2=0,t[N],n; struct kruskal{ int _G[N],_to[N],_nxt[N],sz,f[18][N],dep[N],pa[N],dfn[N],maxn[N],dfsc; inline void init(){sz=dfsc=0;} inline void add(int u,int v){ _to[++sz]=v;_nxt[sz]=_G[u];_G[u]=sz; } int gf(int x){return pa[x]==x?x:pa[x]=gf(pa[x]);} void dfs(int u,int fa){ int i,v; dep[u]=dep[f[0][u]=fa]+1; dfn[u]=++dfsc; for(i=1;(1<<i)<dep[u];++i)f[i][u]=f[i-1][f[i-1][u]]; for(i=_G[u];i;i=_nxt[i])if((v=_to[i])!=fa)dfs(v,u); maxn[u]=dfsc; } inline void build1(){ int i,u,v,x,y,tot; for(i=0;i<n;++i)pa[i]=i; for(tot=u=n-1;u>=0;--u) for(i=G[u];i;i=nxt[i])if((v=to[i])>u&&(x=gf(u))!=(y=gf(v))){ add(x,y); pa[y]=x; if(!--tot)return; } } inline void build2(){ int i,u,v,x,y,tot; for(i=0;i<n;++i)pa[i]=i; for(tot=n-1,u=0;u<n;++u) for(i=G[u];i;i=nxt[i])if((v=to[i])<u&&(x=gf(u))!=(y=gf(v))){ add(x,y); pa[y]=x; if(!--tot)return; } } inline int query1(int u,int L){ for(short i=17;i>=0;--i)if((1<<i)<dep[u]&&f[i][u]>=L)u=f[i][u]; return u; } inline int query2(int u,int R){ for(short i=17;i>=0;--i)if((1<<i)<dep[u]&&f[i][u]<=R)u=f[i][u]; return u; } }a,b; inline int cmp(int x,int y){return a.dfn[x]<a.dfn[y];} inline void add(int u,int v){ to[++sz1]=v;nxt[sz1]=G[u];G[u]=sz1; to[++sz1]=u;nxt[sz1]=G[v];G[v]=sz1; } int ins(int pre,int L,int R,int x){ int o=++sz2; cnt[o]=cnt[pre]+1; if(L<R){ int M=L+R>>1; if(x<=M){lc[o]=ins(lc[pre],L,M,x);rc[o]=rc[pre];} else{rc[o]=ins(rc[pre],M+1,R,x);lc[o]=lc[pre];} } return o; } bool query(int u,int v,int L,int R,int x,int y){ if(x<=L&&y>=R)return cnt[v]-cnt[u]; int M=L+R>>1; if(x<=M&&query(lc[u],lc[v],L,M,x,y))return 1; if(y>M&&query(rc[u],rc[v],M+1,R,x,y))return 1; return 0; } int main(){ int m,q,i,u,v,x,y; n=rd();m=rd();q=rd(); for(i=0;i<m;++i){ u=rd();v=rd(); add(u,v); } a.init();a.build1();a.dfs(0,-1); b.init();b.build2();b.dfs(n-1,-1); for(i=0;i<n;++i)t[i]=i; sort(t,t+n,cmp); for(i=1;i<=n;++i)rt[i]=ins(rt[i-1],1,n,b.dfn[t[i-1]]); while(q--){ u=rd();v=rd();x=rd();y=rd(); u=a.query1(u,x);v=b.query2(v,y); puts(query(rt[a.dfn[u]-1],rt[a.maxn[u]],1,n,b.dfn[v],b.maxn[v])?"1":"0"); } return 0; }
LOJ/UOJ代码(交互):
#include<cstdio> #include<algorithm> #include<vector> #include "werewolf.h" using namespace std; const int N=200050; const int M=800050; char rB[1<<21],*rS,*rT; inline char gc(){return rS==rT&&(rT=(rS=rB)+fread(rB,1,1<<21,stdin),rS==rT)?EOF:*rS++;} inline int rd(){ char c=gc(); while(c<48||c>57)c=gc(); int x=c&15; for(c=gc();c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c&15); return x; } int G[N],to[M],nxt[M],sz1=0,cnt[N<<5],lc[N<<5],rc[N<<5],rt[N],sz2=0,t[N],n; struct kruskal{ int _G[N],_to[N],_nxt[N],sz,f[18][N],dep[N],pa[N],dfn[N],maxn[N],dfsc; inline void init(){sz=dfsc=0;} inline void add(int u,int v){ _to[++sz]=v;_nxt[sz]=_G[u];_G[u]=sz; } int gf(int x){return pa[x]==x?x:pa[x]=gf(pa[x]);} void dfs(int u,int fa){ int i,v; dep[u]=dep[f[0][u]=fa]+1; dfn[u]=++dfsc; for(i=1;(1<<i)<dep[u];++i)f[i][u]=f[i-1][f[i-1][u]]; for(i=_G[u];i;i=_nxt[i])if((v=_to[i])!=fa)dfs(v,u); maxn[u]=dfsc; } inline void build1(){ int i,u,v,x,y,tot; for(i=0;i<n;++i)pa[i]=i; for(tot=u=n-1;u>=0;--u) for(i=G[u];i;i=nxt[i])if((v=to[i])>u&&(x=gf(u))!=(y=gf(v))){ add(x,y); pa[y]=x; if(!--tot)return; } } inline void build2(){ int i,u,v,x,y,tot; for(i=0;i<n;++i)pa[i]=i; for(tot=n-1,u=0;u<n;++u) for(i=G[u];i;i=nxt[i])if((v=to[i])<u&&(x=gf(u))!=(y=gf(v))){ add(x,y); pa[y]=x; if(!--tot)return; } } inline int query1(int u,int L){ for(short i=17;i>=0;--i)if((1<<i)<dep[u]&&f[i][u]>=L)u=f[i][u]; return u; } inline int query2(int u,int R){ for(short i=17;i>=0;--i)if((1<<i)<dep[u]&&f[i][u]<=R)u=f[i][u]; return u; } }a,b; inline int cmp(int x,int y){return a.dfn[x]<a.dfn[y];} inline void add(int u,int v){ to[++sz1]=v;nxt[sz1]=G[u];G[u]=sz1; to[++sz1]=u;nxt[sz1]=G[v];G[v]=sz1; } int ins(int pre,int L,int R,int x){ int o=++sz2; cnt[o]=cnt[pre]+1; if(L<R){ int M=L+R>>1; if(x<=M){lc[o]=ins(lc[pre],L,M,x);rc[o]=rc[pre];} else{rc[o]=ins(rc[pre],M+1,R,x);lc[o]=lc[pre];} } return o; } bool query(int u,int v,int L,int R,int x,int y){ if(x<=L&&y>=R)return cnt[v]-cnt[u]; int M=L+R>>1; if(x<=M&&query(lc[u],lc[v],L,M,x,y))return 1; if(y>M&&query(rc[u],rc[v],M+1,R,x,y))return 1; return 0; } vector<int> check_validity(int N,vector<int> X,vector<int> Y,vector<int> S,vector<int> E,vector<int> L,vector<int> R){ int m=X.size(),q=S.size(),i,u,v,x,y; vector<int> s; n=N; for(i=0;i<m;++i){ u=X[i];v=Y[i]; add(u,v); } a.init();a.build1();a.dfs(0,-1); b.init();b.build2();b.dfs(n-1,-1); for(i=0;i<n;++i)t[i]=i; sort(t,t+n,cmp); for(i=1;i<=n;++i)rt[i]=ins(rt[i-1],1,n,b.dfn[t[i-1]]); for(i=0;i<q;++i){ u=S[i];v=E[i];x=L[i];y=R[i]; u=a.query1(u,x);v=b.query2(v,y); s.push_back(query(rt[a.dfn[u]-1],rt[a.maxn[u]],1,n,b.dfn[v],b.maxn[v])); } return s; }