其他分享
首页 > 其他分享> > BZOJ - 3786 星系探索

BZOJ - 3786 星系探索

作者:互联网

\(\text{Description}\)

传送门

\(\text{Solution}\)

据说是伪 \(\text{ETT}\)。

但既然不会那玩意儿,所以把它称作——欧拉序 \(+\) 平衡树。

具体怎么做呢?我们设点 \(u\) 的进入,出去的时间戳为 \(st_u,ed_u\)。然后在欧拉序序列上建一棵平衡树,给 \(st_u\) 的权值赋为 \(val_u\),给 \(ed_u\) 的权值赋为 \(-val_u\)。

详见代码。

\(\text{Code}\)

#include <cstdio>

#define rep(i,_l,_r) for(register signed i=(_l),_end=(_r);i<=_end;++i)
#define fep(i,_l,_r) for(register signed i=(_l),_end=(_r);i>=_end;--i)
#define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i])
#define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i])
#define print(x,y) write(x),putchar(y)

template <class T> inline T read(const T sample) {
    T x=0; int f=1; char s;
    while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
    while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
    return x*f;
}
template <class T> inline void write(const T x) {
    if(x<0) return (void) (putchar('-'),write(-x));
    if(x>9) write(x/10);
    putchar(x%10^48);
}
template <class T> inline T Max(const T x,const T y) {if(x>y) return x; return y;}
template <class T> inline T Min(const T x,const T y) {if(x<y) return x; return y;}
template <class T> inline T fab(const T x) {return x>0?x:-x;}
template <class T> inline T gcd(const T x,const T y) {return y?gcd(y,x%y):x;}
template <class T> inline T lcm(const T x,const T y) {return x/gcd(x,y)*y;}

typedef long long ll;

const int maxn=1e5+5;

int head[maxn],nxt[maxn],to[maxn],cnt,n,m,idx=1,Val[maxn<<1],l[maxn],r[maxn],a[maxn];
char str[10];
struct Splay {
    int rt;
    struct node {
        int pos,neg,val,son[2],op,f;
        ll sum,tag;
        
        /*
        	pos 与 neg:自己为根的子树有多少个 st/ed,这个是用来算加 k 值时的正负。
        */
    } t[maxn<<1];

    bool dir(int x) {return t[t[x].f].son[1]==x;}

    void add(int x,int fa,bool dir) {
        if(x) t[x].f=fa;
        if(fa) t[fa].son[dir]=x;
    }

    void upd(int o,int k) {
        if(!o) return;
        t[o].tag+=k;
        t[o].sum+=1ll*k*(t[o].pos-t[o].neg);
        t[o].val+=1ll*k*t[o].op;
    }

    void pushDown(int o) {
        if(!o||(!t[o].tag)) return;
        upd(t[o].son[0],t[o].tag),upd(t[o].son[1],t[o].tag);
        t[o].tag=0;
    }

    void pushUp(int o) {
        if(!o) return;
        t[o].sum=t[t[o].son[0]].sum+t[t[o].son[1]].sum+t[o].val;
        t[o].pos=t[t[o].son[0]].pos+t[t[o].son[1]].pos+(t[o].op==1);
        t[o].neg=t[t[o].son[0]].neg+t[t[o].son[1]].neg+(t[o].op==-1);
    }

    void rotate(int x) {
        int fa=t[x].f,ffa=t[fa].f,dx=dir(x),df=dir(fa);
        pushDown(fa),pushDown(x);
        add(t[x].son[dx^1],fa,dx);
        add(fa,x,dx^1);
        add(x,ffa,df);
        pushUp(fa),pushUp(x);
    }

    void splay(int x,int goal) {
        for(int fa;(fa=t[x].f)^goal;rotate(x))
            if(t[fa].f^goal) rotate(dir(x)==dir(fa)?fa:x);
        if(!goal) rt=x;
    }

    int pre(int x) {x=t[x].son[0]; while(t[x].son[1]) x=t[x].son[1]; return x;}

    int suf(int x) {x=t[x].son[1]; while(t[x].son[0]) x=t[x].son[0]; return x;}

    void Build(int &o,int l,int r,int fa) {
        o=l+r>>1; t[o].f=fa;
        if(Val[o]>0) t[o].op=1,t[o].val=Val[o]-1;
        else t[o].op=-1,t[o].val=Val[o]+1;
        if(l<o) Build(t[o].son[0],l,o-1,o);
        if(r>o) Build(t[o].son[1],o+1,r,o);
        pushUp(o);
    }

    ll Query(int u) {
        int x,y; 
        splay(l[1],0),x=pre(l[1]);
        splay(l[u],0),y=suf(l[u]);
        splay(x,0),splay(y,x);
        return t[t[y].son[0]].sum;
    }

    void Add(int u,int k) {
        int x,y;
        splay(l[u],0),x=pre(l[u]);
        splay(r[u],0),y=suf(r[u]);
        splay(x,0),splay(y,x);
        upd(t[y].son[0],k),pushDown(t[y].son[0]);
    }

    void Modify(int u,int v) {
        int x,y;
        splay(l[u],0),x=pre(l[u]);
        splay(r[u],0),y=suf(r[u]);
        splay(x,0),splay(y,x);
        int Son=t[y].son[0]; t[Son].f=t[y].son[0]=0; pushUp(y);
        splay(l[v],0);
        int nxt=suf(l[v]); splay(nxt,l[v]);
        t[Son].f=nxt,t[nxt].son[0]=Son;
        pushUp(Son),pushUp(nxt);
    }
} T;

void addEdge(int u,int v) {
    nxt[++cnt]=head[u],to[cnt]=v,head[u]=cnt;
}

void dfs(int u) {
    l[u]=++idx,Val[idx]=a[u]+1; 
    erep(i,u) dfs(to[i]);
    r[u]=++idx,Val[idx]=-a[u]-1; 
}

int main() {
    int x,y;
    n=read(9);
    rep(i,2,n) x=read(9),addEdge(x,i);
    rep(i,1,n) a[i]=read(9);
    dfs(1);
    T.Build(T.rt,1,idx+1,0);
    for(int m=read(9);m;--m) {
        scanf("%s",str); x=read(9);
        if(str[0]=='Q') print(T.Query(x),'\n');
        else if(str[0]=='C') y=read(9),T.Modify(x,y);
        else y=read(9),T.Add(x,y);
    }
    return 0;
}

标签:nxt,星系,int,st,splay,read,const,3786,BZOJ
来源: https://www.cnblogs.com/AWhiteWall/p/14238632.html