zoukankan      html  css  js  c++  java
  • 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
    ",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
  • 相关阅读:
    python全栈学习--day57(响应式页面-@media介绍,移动端单位介绍,Bootstrap学习)
    网络编程-Socket介绍
    网络编程-五层协议详解
    python-封装
    python- 类的多态与多态性
    python-接口类与抽象类
    python-类的组合和使用
    python-类继承与重用
    python-面向对象编程小结
    python-属性的查找与绑定方法
  • 原文地址:https://www.cnblogs.com/DriverLao/p/9471119.html
Copyright © 2011-2022 走看看