ACM多校联赛7 2018 Multi-University Training Contest 7 1009 Tree

【题意概述】

  给一棵以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\n",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 }
View Code

猜你喜欢

转载自www.cnblogs.com/DriverLao/p/9471119.html