• 数据结构&图论:欧拉游览树


    ETT可以称为欧拉游览树,它是一种和欧拉序有关的动态树(LCT是解决动态树问题的一种方案,这是另一种)

    dfs序和欧拉序是把树问题转化到区间问题上然后再用数据结构去维护的利器

    通过借助这两种形式能够完成子树的查询和修改,这是LCT所不能胜任的工作

    所谓的ETT就是通过动态维护欧拉序来实现动态树

    它能完成换父亲(Cut和Link操作)

    修改子树(LCT实现不了)

    查询结点到根的信息

    当然它对比于LCT还是有局限性的

    这些操作通过DFS序+Splay也可以完成

    只不过我们通俗地把欧拉序+Splay称作ETT而已

    这个代码在我交上去的时候WA了一发,printf函数在处理long long的时候一定要小心

    代码细节等以后对DFS序和欧拉序了解更加充分以及对数据结构掌握的更好的时候再回过头来看

      1 #include<cstdio>
      2 using namespace std;
      3 const int maxn=200005;
      4 const int maxm=200005;
      5 int n,cnt,tot,m;
      6 int a[maxn],g[maxn];
      7 int lch[maxn],rch[maxn],dfn[maxn];
      8 int fa[maxn],size[maxn],mark[maxn];
      9 long long lazy[maxn],sum[maxn],val[maxn];
     10 int ch[maxn][2];
     11 struct Edge
     12 {
     13     int t,next;
     14 }e[maxm];
     15 inline int read()
     16 {
     17     int x=0,f=1;char ch=getchar();
     18     while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
     19     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     20     return x*f;
     21 }
     22 void addedge(int u,int v)
     23 {
     24     cnt++;
     25     e[cnt].t=v;e[cnt].next=g[u];
     26     g[u]=cnt;
     27 }
     28 void dfs(int x)  //计算欧拉序 
     29 {
     30     lch[x]=++tot;
     31     dfn[lch[x]]=x;
     32     for(int tmp=g[x];tmp;tmp=e[tmp].next)
     33         dfs(e[tmp].t);
     34     rch[x]=++tot;
     35     dfn[rch[x]]=-x;
     36 }
     37 void push_down(int x)
     38 {
     39     if(x&&fa[x]) push_down(fa[x]);
     40     if(x==0||lazy[x]==0) return;
     41     lazy[ch[x][0]]+=lazy[x];
     42     lazy[ch[x][1]]+=lazy[x];
     43     val[ch[x][0]]+=lazy[x]*mark[ch[x][0]];
     44     val[ch[x][1]]+=lazy[x]*mark[ch[x][1]];
     45     sum[ch[x][0]]+=(long long)size[ch[x][0]]*lazy[x];
     46     sum[ch[x][1]]+=(long long)size[ch[x][1]]*lazy[x];
     47     lazy[x]=0;
     48 }
     49 int dir(int x)
     50 {
     51     return ch[fa[x]][1]==x;
     52 }
     53 void push_up(int x)
     54 {
     55     sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x];
     56     size[x]=size[ch[x][0]]+size[ch[x][1]]+mark[x];
     57 }
     58 void rotate(int x,int d)
     59 {
     60     int tmp=ch[x][d^1];
     61     ch[x][d^1]=ch[tmp][d];
     62     if(ch[x][d^1]) fa[ch[x][d^1]]=x;
     63     fa[tmp]=fa[x];
     64     if(fa[x]) ch[fa[x]][dir(x)]=tmp;
     65     fa[x]=tmp;
     66     ch[tmp][d]=x;
     67     push_up(x);push_up(tmp);
     68 }
     69 void splay(int x,int goal)
     70 {
     71     push_down(x);
     72     while(fa[x]!=goal)
     73     {
     74         if(fa[fa[x]]!=goal&&dir(x)==dir(fa[x]))
     75             rotate(fa[fa[x]],dir(x)^1);
     76         rotate(fa[x],dir(x)^1);
     77     }
     78 }
     79 int find_left(int x)
     80 {
     81     splay(x,0);
     82     x=ch[x][0];
     83     while(ch[x][1]) x=ch[x][1];
     84     return x;
     85 }
     86 int find_right(int x)
     87 {
     88     splay(x,0);
     89     x=ch[x][1];
     90     while(ch[x][0]) x=ch[x][0];
     91     return x;
     92 }
     93 int build(int l,int r)
     94 {
     95     if(l>r) return 0;
     96     int mid=(l+r)>>1;
     97     if(mid<r)
     98     {
     99         ch[mid][1]=build(mid+1,r);
    100         fa[ch[mid][1]]=mid;
    101     }
    102     if(l<mid)
    103     {
    104         ch[mid][0]=build(l,mid-1);
    105         fa[ch[mid][0]]=mid;
    106     }
    107     if(dfn[mid]>0) val[mid]=a[dfn[mid]];
    108     else val[mid]=-a[-dfn[mid]];
    109     
    110     if(dfn[mid]>0) mark[mid]=1;
    111     else mark[mid]=-1;
    112     
    113     push_up(mid);
    114     return mid;
    115 }
    116 int main()
    117 {
    118     int x,y; 
    119     char opt;
    120     n=read();
    121     for(int i=2;i<=n;i++)
    122     {
    123         x=read();
    124         addedge(x,i);
    125     }
    126     dfs(1);
    127     for(int i=1;i<=n;i++) a[i]=read();
    128     build(1,tot+1);
    129     m=read();
    130     while(m--)
    131     {
    132         opt=getchar();
    133         while(opt!='Q'&&opt!='C'&&opt!='F') opt=getchar();
    134         x=read();
    135         if(opt=='Q')
    136         {
    137             splay(lch[x],0);
    138             printf("%lld
    ",sum[ch[lch[x]][0]]+val[lch[x]]);
    139         }
    140         else if(opt=='C')
    141         {
    142             y=read();
    143             int aa=find_left(lch[x]),bb=find_right(rch[x]);
    144             splay(aa,0);splay(bb,aa);
    145             int tmp=ch[bb][0];
    146             ch[bb][0]=0;
    147             push_up(bb);push_up(aa);
    148             x=find_left(rch[y]);
    149             splay(x,0);splay(rch[y],x);
    150             fa[tmp]=rch[y];
    151             ch[rch[y]][0]=tmp;
    152             push_up(rch[y]);push_up(x);
    153         }
    154         else
    155         {
    156             y=read();
    157             int aa=find_left(lch[x]),bb=find_right(rch[x]);
    158             splay(aa,0);splay(bb,aa);
    159             lazy[ch[bb][0]]+=y;
    160             val[ch[bb][0]]+=y*mark[ch[bb][0]];
    161             sum[ch[bb][0]]+=(long long)size[ch[bb][0]]*y;
    162         }
    163     }
    164     return 0;
    165 }
  • 相关阅读:
    7-31 jmu-分段函数l (20 分)
    7-29 jmu-python-不同进制数 (10 分)
    7-28 摄氏温度转换华氏温度 (5 分)
    7-23 图的字典表示 (20 分)
    7-24 判断素数 (20 分)
    7-22 输出10个不重复的英文字母 (50 分)
    【转载】C#批量插入数据到Sqlserver中的三种方式
    天气预报api-汇总
    【转载】VS2015 + EF6连接MYSQL5.6
    【转摘】TFS上分支和标签的用法
  • 原文地址:https://www.cnblogs.com/aininot260/p/9517665.html
Copyright © 2020-2023  润新知