【题意概述】
给一棵以1为根的树,树上的每个节点有一个ai值,代表它可以传送到自己的ai倍祖先,如果不存在则传送出这棵树。现在询问某个节点传送出这棵树需要多少步。
【题解】
其实是把“弹飞绵羊”那道题从序列上搬到了树上,解法其实类似。
我们可以用LCT维护传送的关系,若点i存在ai倍祖先,那么就把他们link起来,否则就把i与特殊节点n+1给link起来。
询问某个点要传送多少次时,就是询问这个点到n+1有多远,我们在LCT上取出这一段,查询size即可。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #define N (100010) 6 #define ls (c[u][0]) 7 #define rs (c[u][1]) 8 #define LL long long 9 #define rg register 10 using namespace std; 11 int T,n,m,opt,cnt,tot,last[N],k[N],dfn[N],dep[N],p[N][20]; 12 struct edge{ 13 int to,pre; 14 }e[N]; 15 char buf[20000010],*ptr=buf-1; 16 template<typename T> 17 inline void read(T &k) 18 { 19 int f=1; k=0; char c=*++ptr; 20 while(c<'0' || c>'9') c=='-'&&(f=-1), c=*++ptr; 21 while(c<='9' && c>='0') k=k*10+c-'0', c=*++ptr; 22 k*=f; 23 } 24 25 struct Link_Cut_Tree{ 26 int top,c[N][2],fa[N],rev[N],size[N],q[N]; 27 inline void clear(){ 28 for(rg int i=1;i<=n+2;i++) c[i][0]=c[i][1]=size[i]=rev[i]=fa[i]=0; 29 } 30 inline void pushdown(int u){ 31 if(rev[u]) rev[ls]^=1,rev[rs]^=1,rev[u]^=1,swap(ls,rs); 32 } 33 inline void pushup(int u){ 34 size[u]=1; 35 if(ls) size[u]+=size[ls]; 36 if(rs) size[u]+=size[rs]; 37 } 38 inline bool isroot(int u){ 39 return c[fa[u]][0]!=u&&c[fa[u]][1]!=u; 40 } 41 inline bool which(int u){ 42 return c[fa[u]][1]==u; 43 } 44 void rotate(int u){ 45 int f=fa[u],gf=fa[f],wh=which(u); 46 if(!isroot(f)) c[gf][which(f)]=u; 47 fa[u]=gf; fa[f]=u; fa[c[u][wh^1]]=f; 48 c[f][wh]=c[u][wh^1]; c[u][wh^1]=f; 49 pushup(f); pushup(u); 50 } 51 void splay(int u){ 52 q[top=1]=u; 53 for(int i=u;!isroot(i);i=fa[i]) q[++top]=fa[i]; 54 for(int i=top;i;i--) pushdown(q[i]); 55 while(!isroot(u)){ 56 if(!isroot(fa[u])) rotate(which(u)==which(fa[u])?fa[u]:u); 57 rotate(u); 58 } 59 pushup(u); 60 } 61 void access(int u){ 62 for(int son=0;u;son=u,u=fa[u]) 63 splay(u),c[u][1]=son,pushup(u); 64 } 65 void makeroot(int u){ 66 access(u); splay(u); rev[u]^=1; 67 } 68 int find(int u){ 69 access(u); splay(u); 70 while(ls) u=ls; splay(u); 71 return u; 72 } 73 void split(int x,int y){ 74 makeroot(x); access(y); splay(y); 75 } 76 void cut(int x,int y){ 77 int xrt=find(x),yrt=find(y); 78 if(xrt!=yrt) return; 79 split(x,y); 80 if(c[y][0]==x) c[y][0]=0,fa[x]=0; 81 pushup(y); 82 } 83 void link(int x,int y){ 84 int xrt=find(x),yrt=find(y); 85 if(xrt==yrt) return; 86 makeroot(x); fa[x]=y; 87 } 88 }t; 89 void dfs(int x,int fa){ 90 dfn[x]=++cnt; dep[x]=dep[fa]+1; p[x][0]=fa; 91 int tmp=log2(dep[x]); 92 for (int i=1;i<=tmp;i++) p[x][i]=p[p[x][i-1]][i-1]; 93 for(rg int i=last[x];i;i=e[i].pre) dfs(e[i].to,x); 94 } 95 inline int anc(int x,int y){ 96 for(rg int i=0;i<=17;i++) if(y&(1<<i)) x=p[x][i]; 97 return x; 98 } 99 inline void Pre(){ 100 for(rg int i=1;i<=n;i++) last[i]=0; 101 cnt=tot=0; 102 t.clear(); 103 } 104 int main(){ 105 fread(buf, 1, sizeof(buf), stdin); 106 read(T); 107 while(T--){ 108 read(n); 109 Pre(); 110 for(rg int i=2;i<=n;i++){ 111 int fa; read(fa); 112 e[++tot]=(edge){i,last[fa]}; last[fa]=tot; 113 } 114 dfs(1,0); 115 // for(rg int i=1;i<=n;i++) printf("%d ",dep[i]); puts("dep"); 116 for(rg int i=1;i<=n;i++){ 117 read(k[i]); 118 if(k[i]>=dep[i]) t.link(dfn[i],n+1); 119 else t.link(dfn[i],dfn[anc(i,k[i])]); 120 } 121 read(m); 122 while(m--){ 123 int opt; read(opt); 124 if(opt==1){ 125 int x; read(x); 126 x=dfn[x]; 127 t.makeroot(x); t.access(n+1); t.splay(n+1); 128 printf("%d ",t.size[n+1]-1); 129 } 130 else{ 131 int x,y; read(x); read(y); 132 if(k[x]>=dep[x]&&y>=dep[x]) continue; 133 if(k[x]>=dep[x]) t.cut(dfn[x],n+1); 134 else t.cut(dfn[x],dfn[anc(x,k[x])]); 135 k[x]=y; 136 if(k[x]>=dep[x]) t.link(dfn[x],n+1); 137 else t.link(dfn[x],dfn[anc(x,k[x])]); 138 } 139 } 140 } 141 return 0; 142 }