link
题意:
给一张n个点m条边的无向图,有q个询问,每次询问给出s,t,l,r,问你能否从s走到t,并且初始为人形,结束时必须为狼形,你是人形的时候必须避开$[1,l)$的节点,狼形的时候必须避开$(r,n]$的节点,你只能在$[L,R]$的节点处变身?
$n,q\leq 2\times 10^5,m\leq 4\times 10^5.$
题解:
get技能——Kruskal重构树
重构树是一个类似堆的结构,节点u比它的所有儿子v的权都要来的小/大(在这题中都有用到),可以用并查集建树。
考虑题中s~t有合法路径相当于,s只经过L~N的点能到达的点集和t只经过1~R的点能到达的点集有交。
那么考虑建出Kruskal最大/小重构树,那么两个点集分别对应到两棵树上的一个子树,求出dfs序转化成两个区间。
把每个点对应到一个坐标$[dfn1,dfn2]$(在两棵树中dfs序上的位置),原问题等价于询问一个矩形$x∈[l1,r1],y∈[l2,r2]$中是否有点,离线树状数组即可。
复杂度$\mathcal{O}(n\log n)$。
code:
1 #include2 #include "werewolf.h" 3 #define rep(i,x,y) for (int i=(x);i<=(y);i++) 4 #define per(i,x,y) for (int i=(x);i>=(y);i--) 5 #define ll long long 6 #define VI vector 7 using namespace std; 8 const int N=2e5+5; 9 int u,v,n,m,Q,top,bit[N]; VI ans,G[N]; 10 struct node{ 11 int x,y,ty,op,id; 12 node(){} 13 node(int x,int y,int ty,int op,int id):x(x),y(y),ty(ty),op(op),id(id){} 14 }q[N*5]; 15 bool cmp(node x,node y){ return x.x y.ty; } 16 struct Kruskal_rebuild_tree{ 17 int cnt,head[N],fa[N],clk,in[N],out[N],f[N][19]; 18 struct edge{ int to,nxt; }e[N]; 19 void adde(int x,int y){ e[++cnt].to=y; e[cnt].nxt=head[x]; head[x]=cnt; } 20 int getfa(int x){ return x==fa[x]?x:fa[x]=getfa(fa[x]); } 21 void dfs(int u,int ty){ 22 rep (i,1,18) f[u][i]=f[f[u][i-1]][i-1]; 23 in[u]=++clk; 24 for (int i=head[u];i;i=e[i].nxt) f[e[i].to][0]=u,dfs(e[i].to,ty); 25 out[u]=clk; 26 } 27 void build(int ty){ 28 cnt=0; rep (x,1,n) fa[x]=x,head[x]=0; 29 if (!ty){ 30 per (x,n,1) 31 for (auto y:G[x]) 32 if (x x; 33 } else{ 34 rep (x,1,n) 35 for (auto y:G[x]) 36 if (x>y&&getfa(x)!=(y=getfa(y))) adde(x,y),fa[y]=x; 37 } 38 rep (i,1,n) if (getfa(i)==i) dfs(i,ty); 39 } 40 int qry(int x,int lim,int ty){ 41 per (i,18,0) 42 if (f[x][i]&&(!ty?f[x][i]>=lim:f[x][i]<=lim)) x=f[x][i]; 43 return x; 44 } 45 }T[2]; 46 void add(int x){ for (;x<=n;x+=x&-x) bit[x]++; } 47 int qry(int x){ int s=0; for (;x;x-=x&-x) s+=bit[x]; return s; } 48 VI check_validity(int _n,VI x,VI y,VI s,VI t,VI l,VI r){ 49 n=_n; m=x.size(),Q=s.size(); 50 rep (i,0,m-1) G[++x[i]].push_back(++y[i]),G[y[i]].push_back(x[i]); 51 T[0].build(0); T[1].build(1); 52 rep (i,1,n) q[++top]=node(T[0].in[i],T[1].in[i],0,0,0); 53 rep (i,0,Q-1){ 54 ++s[i],++t[i],++l[i],++r[i]; 55 int u=T[0].qry(s[i],l[i],0),v=T[1].qry(t[i],r[i],1); 56 int l1=T[0].in[u],r1=T[0].out[u],l2=T[1].in[v],r2=T[1].out[v]; 57 q[++top]=node(r1,r2,1,1,i); 58 if (l1>1) q[++top]=node(l1-1,r2,1,-1,i); 59 if (l2>1) q[++top]=node(r1,l2-1,1,-1,i); 60 if (l1>1&&l2>1) q[++top]=node(l1-1,l2-1,1,1,i); 61 } 62 sort(q+1,q+1+top,cmp); ans.resize(Q); 63 rep (i,1,top) 64 if (!q[i].ty) add(q[i].y); else ans[q[i].id]+=qry(q[i].y)*q[i].op; 65 rep (i,0,Q-1) ans[i]=!!ans[i]; 66 return ans; 67 }