1. 程式人生 > >uoj407 【IOI2018】狼人

uoj407 【IOI2018】狼人

link

 

題意:

 

題解:

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 #include<bits/stdc++.h>
 2 #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<int>
 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.x||x.x==y.x&&x.ty<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<y&&getfa(x)!=(y=getfa(y))) adde(x,y),fa[y]=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 }
View Code