bzoj3786 星系探索(ETT)

ETT就是Euler Tour Tree,用平衡树来维护欧拉序。
而欧拉序可以写成很多形式:
1.The first way is to write down all edges of the tree, directed, in order of DFS. This is how ETT is defined on
2.The second way is to store vertices. Each vertex is added to the array twice: when we descend into it and when we leave it.
3.The third way implies storing vertices too, but now each vertex is added every time when we visit it (when descending from parent and when returning from child)
第一种就是存dfs顺序的有向边,是欧拉遍序的官方定义,不过基本不用。
第二种就是常用的dfs序,括号序,这样每一个子树的点都是一段连续的区间,可以在进去的时候给正权,出来的时候给负权,这样直接加和就是答案了。
第三种就是rmq O(1)求lca经常用到的那个序。

而本题我们用的是第二种。
看一看用ETT我们可以做什么?
我们可以查询根到点的点权和(就是in[x]的前缀和)
我们可以删一棵子树(把对应区间删掉,可以用splay方便的提取区间实现)
我们可以加一棵子树(插入一个区间)
我们可以子树操作。
我们可以求子树和。
我们可以做链操作(求个lca然后分别到根容斥一下?需要可减?)
听说还可以换根?不过看上去巨麻烦x(貌似需要放到lct上,然后多个log,然后就可以实现和top tree同样的功能?)

一些参考资料:国家集训队论文集2014年《浅谈动态树的相关问题及简单拓展》
http://memphis.is-programmer.com/2015/8/7/linkcutmemphis.99293.html

我好像连splay都不会打了qaq

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(T==S){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
inline char get_S(){
    char ch=gc();
    while(ch<'A'||ch>'Z') ch=gc();return ch;
}
int n,fa[N<<1],c[N<<1][2],sz[N<<1],in[N],out[N],dfn=0,w[N],sig[N<<1],rt=0,q[N<<1];
ll v[N<<1],sum[N<<1],tag[N<<1];
vector<int>Son[N];
void dfs(int x){
    in[x]=++dfn;v[dfn]=w[x];sig[dfn]=1;
    for(int i=0;i<Son[x].size();++i) dfs(Son[x][i]);
    out[x]=++dfn;v[dfn]=-w[x];sig[dfn]=-1;
}
inline void update(int p){
    int l=c[p][0],r=c[p][1];
    sz[p]=sz[l]+sz[r]+sig[p];
    sum[p]=sum[l]+sum[r]+v[p];
}
inline void doadd(int p,ll val){
    tag[p]+=val;v[p]+=val*sig[p];sum[p]+=(ll)val*sz[p];
}
inline void pushdown(int p){
    if(!tag[p]) return;
    int l=c[p][0],r=c[p][1];
    if(l) doadd(l,tag[p]);if(r) doadd(r,tag[p]);tag[p]=0;
}
inline void build(int &p,int l,int r){
    int mid=l+r>>1;p=mid;tag[p]=0;
    if(l<mid) build(c[p][0],l,mid-1),fa[c[p][0]]=p;
    if(r>mid) build(c[p][1],mid+1,r),fa[c[p][1]]=p;update(p);
}
inline void rotate(int x,int &k){
    int y=fa[x],z=fa[y],l=x==c[y][1],r=l^1;
    if(y==k) k=x;
    else c[z][y==c[z][1]]=x;
    fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
    c[y][l]=c[x][r];c[x][r]=y;update(y);update(x);
}
inline void splay(int x,int &k){
    int top=0;q[++top]=x;
    for(int xx=x;xx!=k;xx=fa[xx]) q[++top]=fa[xx];
    while(top) pushdown(q[top--]);
    while(x!=k){
        int y=fa[x],z=fa[y];
        if(y!=k){
            if(x==c[y][1]^y==c[z][1]) rotate(x,k);
            else rotate(y,k);
        }rotate(x,k);
    }
}
inline int findpre(int x){
    splay(x,rt);int res=c[x][0];
    while(c[res][1]) res=c[res][1];
    return res;
}
inline int findsucc(int x){
    splay(x,rt);int res=c[x][1];
    while(c[res][0]) res=c[res][0];
    return res;
}
inline int split(int xx,int yy){
    int x=findpre(xx),y=findsucc(yy);
    splay(x,rt);splay(y,c[rt][1]);return c[y][0];
}
inline int del1(int l,int r){
    int x=split(l,r),y=fa[x];
    c[y][0]=fa[x]=0;update(y);update(fa[y]);return x;
}inline void add(int l,int r,int val){
    int x=split(l,r),y=fa[x];
    doadd(x,val);update(y);update(fa[y]);
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();dfn=1;
    for(int i=2;i<=n;++i) Son[read()].push_back(i);
    for(int i=1;i<=n;++i) w[i]=read();dfs(1);
    build(rt,1,n*2+2);int m=read();
    while(m--){
        char op=get_S();int x=read();
        if(op=='Q'){
            splay(in[x],rt);
            printf("%lld\n",sum[c[in[x]][0]]+v[in[x]]);continue;
        }int y=read();
        if(op=='C'){
            x=del1(in[x],out[x]);
            int xx=findpre(out[y]),yy=out[y];
            splay(xx,rt);splay(yy,c[rt][1]);c[yy][0]=x;fa[x]=yy;update(yy);update(xx);
        }else add(in[x],out[x],y);
    }return 0;
}
阅读更多
版权声明:转载附上原文地址即可~欢迎各位神犇来虐~ https://blog.csdn.net/Icefox_zhx/article/details/80688766
上一篇bzoj3007 拯救小云公主(二分答案+并查集)
下一篇CF414E Mashmokh's Designed Problem(ETT+二分)
想对作者说点什么? 我来说一句
相关热词

没有更多推荐了,返回首页

关闭
关闭
关闭