• bzoj3786: 星系探索


    传送门

    一个裸的splay维护括号序列的题。

    跟弹飞绵羊几乎一毛一样,只需把进栈的点权值设为w,出栈点权值设为-w即可。

    多了一个子树加的操作,就把子树split出来,打上标记再merge回去就好了。

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    const int N=600007;
    typedef long long LL;
    using namespace std;
    int n,m,val[N];
    char o[10];
    
    template<typename T>void read(T &x)  {
        char ch=getchar(); x=0; T f=1;
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    
    int ecnt,fir[N],nx[N],to[N];
    void add(int u,int v) {
        nx[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
    }
    
    int dfn[2][N],v[N],f[N],dfs_clock,tot;
    void dfs(int x) {
        dfn[0][x]=++dfs_clock;
        v[dfn[0][x]]=val[x];
        f[dfn[0][x]]=1;
        for(int i=fir[x];i;i=nx[i]) 
            dfs(to[i]);
        dfn[1][x]=++dfs_clock;
        v[dfn[1][x]]=-val[x];
        f[dfn[1][x]]=-1;
    }
    
    int p[N],ch[N][2];
    LL sum[N],sumf[N],lz[N];
    #define lc ch[x][0]
    #define rc ch[x][1] 
    void update(int x) { 
        sum[x]=(LL)v[x]+sum[lc]+sum[rc];
        sumf[x]=(LL)f[x]+sumf[lc]+sumf[rc]; 
    }
    
    void ADD(int x,int w) {
        v[x]+=(LL)f[x]*w;
        sum[x]+=sumf[x]*w;
        lz[x]+=w;
    }
    
    void down(int x) {
        if(!lz[x]) return;
        if(lc) ADD(lc,lz[x]); 
        if(rc) ADD(rc,lz[x]);
        lz[x]=0;
    }
    
    int build(int sz) {
        if(!sz) return 0;
        int ls,rs,x;
        ls=build(sz>>1);
        x=++tot;
        rs=build(sz-(sz>>1)-1);
        if(ls) p[ls]=x; lc=ls;
        if(rs) p[rs]=x; rc=rs;
        update(x);
        return x;
    }
    
    void rotate(int x) {
        int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1;
        if(z) ch[z][y==ch[z][1]]=x; p[x]=z;
        ch[y][l]=ch[x][r]; p[ch[x][r]]=y;
        ch[x][r]=y; p[y]=x;
        update(y); update(x);
    }
    
    void splay(int x,int FA=0) {
        static int g[N],top=0,tp;
        for(tp=x;tp!=FA;tp=p[tp]) g[++top]=tp;
        g[++top]=tp;
        while(top) down(g[top--]);
        for(;p[x]!=FA;rotate(x)) {
            int y=p[x],z=p[y];
            if(z!=FA) ((x==ch[y][1])^(y==ch[z][1]))?rotate(x):rotate(y); 
        } 
    }
    
    int pre(int x) {
        splay(x); x=lc;
        while(rc) x=rc;
        return x;
    }
    
    int nxt(int x) {
        splay(x); x=rc;
        while(lc) x=lc;
        return x;
    }
    
    int split(int x) {//x为左边 最后一个 
        splay(x); int y=rc; 
        rc=p[y]=0; 
        update(x); return y;
    }
    
    void merge(int x,int y) {
        splay(x); splay(y);
        while(rc) x=rc; splay(x);
        rc=y; p[y]=x; update(x);
    }
    
    int main() {
    #ifdef DEBUG
        freopen(".in","r",stdin);
        freopen(".out","w",stdout);
    #endif
        read(n);
        for(int i=2;i<=n;i++) {
            int fa; read(fa);
            add(fa,i);
        }
        for(int i=1;i<=n;i++) read(val[i]);
        dfs(1);
        int x=2*n+1,y=2*n+2;
        ch[x][1]=y; p[y]=x;
        ch[y][0]=build(2*n); p[ch[y][0]]=y;
        update(y); update(x);
        read(m);
        while(m--) {
            scanf("%s",o);
            int x,y,w; read(x);
            if(o[0]=='Q') {
                int z=nxt(dfn[0][x]);
                splay(z);
                printf("%lld
    ",sum[ch[z][0]]);
            }
            else if(o[0]=='C') {
                read(y);
                int l=pre(dfn[0][x]);
                split(l);
                int r=split(dfn[1][x]);
                merge(l,r);
                split(dfn[0][y]);
                merge(dfn[0][y],dfn[0][x]);
                merge(dfn[0][x],dfn[1][y]);
            }
            else if(o[0]=='F') {
                read(w);
                int l=pre(dfn[0][x]);
                split(l);
                int r=split(dfn[1][x]);
                splay(dfn[0][x]);
                ADD(dfn[0][x],w);
                merge(l,dfn[0][x]);
                merge(dfn[0][x],r);
            }
        }
        return 0;
    }
    /*
    3
    1
    1
    4 5 7
    5
    Q 2
    F 1 3
    Q 2
    C 2 3
    Q 2
    */
    View Code

    ·

  • 相关阅读:
    HTML5新特性之文件和二进制数据的操作
    HTML5本地存储之IndexedDB
    HTML5新标签之Canvas
    HTML5 Canvas实战之烟花效果
    Asp.NET core/net 5接口返回实体含有long/int64的属性序列后最后几位变为0的解决
    Aero for WTL application
    C++WTL基于MCI的音频播放器源码
    c++ 深拷贝,浅拷贝,赋值操作的调用情况
    发布一个生成按钮图片的工具 c#写的
    贴图:CImage VS Bitmap
  • 原文地址:https://www.cnblogs.com/Achenchen/p/8538314.html
Copyright © 2020-2023  润新知