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\n",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 }