zoukankan      html  css  js  c++  java
  • [BZOJ3786]星系探索

    ETT的模板题。

    我们把欧拉序标出来, 把入栈视作+,出栈视作-。

    它的子树一定是在两个欧拉序中间的。

    然后把欧拉序当做一个区间维护,换父亲就把左右两端这个区间挪到它的新父亲的入栈的右边。用splay维护一下就行了。

    但是!这个@#$%^&题卡数组版splay?????

    但是不卡spaly???(单旋splay)

    ??????

    /**************************************************************
        Problem: 3786
        User: 568877201
        Language: C++
        Result: Accepted
        Time:26980 ms
        Memory:17020 kb
    ****************************************************************/
     
    #include <iostream>
    #include <cstdio>
    using namespace std;
    const int N=200005;
    struct Splay {
        int ch[2],fa,ld,rd,ty;
        long long tag,sum,val;
    } t[N];
    int rnk[N],dfn1[N],dfn2[N],tim,rt,nxt[N],to[N],ecnt,head[N],a[N];
    inline int read() {
        char c=getchar();
        int x=0,f=1;
        while(c<'0'||c>'9') {
            if(c=='-')f=-1;
            c=getchar();
        }
        while(c>='0'&&c<='9') {
            x=x*10+c-'0';
            c=getchar();
        }
        return x*f;
    }
    inline void pushup(int x) {
        t[x].ld=t[t[x].ch[0]].ld+t[t[x].ch[1]].ld+(t[x].ty==1);
        t[x].rd=t[t[x].ch[0]].rd+t[t[x].ch[1]].rd+(t[x].ty==-1);
        t[x].sum=t[t[x].ch[0]].sum+t[t[x].ch[1]].sum+(t[x].val);
    }
    inline void add(int bg,int ed) {
        nxt[++ecnt]=head[bg];
        to[ecnt]=ed;
        head[bg]=ecnt;
    }
    inline void doit(int x,int v) {
        t[x].val+=1ll*v*t[x].ty;
        t[x].sum+=1ll*v*(t[x].ld-t[x].rd);
        t[x].tag+=1ll*v;
    }
    inline void pushdown(int x) {
        if(t[x].tag) {
            if(t[x].ch[0]) doit(t[x].ch[0],t[x].tag);
            if(t[x].ch[1]) doit(t[x].ch[1],t[x].tag);
            t[x].tag=0;
        }
    }
    inline void rotate(int x) {
        int f=t[x].fa,ff=t[f].fa;
        bool tag=x==t[t[x].fa].ch[1];
        t[f].ch[tag]=t[x].ch[tag^1];
        t[t[f].ch[tag]].fa=f;
        t[x].ch[tag^1]=f;
        t[f].fa=x;
        t[x].fa=ff;
        if(ff) t[ff].ch[f==t[ff].ch[1]]=x;
        pushup(f);
        pushup(x);
    }
    void PUSHDOWN(int x) {
        if(t[x].fa) PUSHDOWN(t[x].fa);
        pushdown(x);
    }
    inline void splay(int x,int tar) {
        PUSHDOWN(x);
        for(int f; (f=t[x].fa)!=tar; rotate(x)) if(t[f].fa!=tar) rotate((x==t[t[x].fa].ch[1])==(f==t[t[f].fa].ch[1])?f:x);
        if(!tar) rt=x;
    }
    int build(int l,int r,int f) {
        int mid=l+r>>1,x=mid;
        t[x].fa=f;
        if(rnk[x]>0) t[x].val=a[rnk[x]],t[x].ty=1;
        else t[x].val=-a[-rnk[x]],t[x].ty=-1;
        if(l<mid)t[x].ch[0]=build(l,mid-1,x);
        if(mid<r)t[x].ch[1]=build(mid+1,r,x);
        pushup(x);
        return x;
    }
    inline int Nxt() {
        int x=t[rt].ch[1];
        while(t[x].ch[0]) x=t[x].ch[0];
        return x;
    }
    inline int pre() {
        int x=t[rt].ch[0];
        while(t[x].ch[1]) x=t[x].ch[1];
        return x;
    }
    inline void split(int &x,int &y) {
        splay(x,0);
        x=pre();
        splay(y,0);
        y=Nxt();
        splay(x,0);
        splay(y,x);
    }
    inline void query(int x) {
        int a=dfn1[1],b=dfn1[x];
        split(a,b);
        printf("%lld
    ",t[t[b].ch[0]].sum);
    }
    inline void change(int x,int f) {
        int a=dfn1[x],b=dfn2[x];
        split(a,b);
        int c=t[b].ch[0];
        t[b].ch[0]=t[c].fa=0;
        pushup(b),pushup(a);
        a=dfn1[f];
        splay(a,0);
        b=Nxt();
        splay(b,a);
        t[b].ch[0]=c;
        t[c].fa=b;
        pushup(b),pushup(a);
    }
    inline void addv(int x,int v) {
        int a=dfn1[x],b=dfn2[x];
        split(a,b);
        doit(t[b].ch[0],v);
    }
    void dfs(int x) {
        dfn1[x]=++tim;
        rnk[tim]=x;
        for(int i=head[x]; i; i=nxt[i]) dfs(to[i]);
        dfn2[x]=++tim;
        rnk[tim]=-x;
    }
    int n;
    signed main() {
        n=read();
        for(int i=2; i<=n; i++) add(read(),i);
        for(int i=1; i<=n; i++) a[i]=read();
        tim=1;
        dfs(1);
        tim++;
        rt=build(1,tim,0);
        int m;
        m=read();
        char opt[10];
        int x,y,z;
        while(m--) {
            scanf("%s",opt);
            switch (opt[0]) {
                case 'Q':
                    query(read());
                    break;
                case 'C':
                    x=read(),change(x,read());
                    break;
                case 'F':
                    x=read(),addv(x,read());
                    break;
            }
        }
    }
    AC

     如果哪位dalao看出我的数组版哪里有锅,感激不尽。。。

    /**************************************************************
        Problem: 3786
        User: 568877201
        Language: C++
        Result: Time_Limit_Exceed
    ****************************************************************/
     
    #include <iostream>
    #include <cstdio>
    using namespace std;
    const int N=200005;
    int ch[N][2],fa[N],ld[N],rd[N],rnk[N],dfn1[N],dfn2[N],tim,ty[N],rt,nxt[N],to[N],ecnt,head[N],a[N];
    long long tag[N],sum[N],val[N];
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    inline void pushup(int x){
        ld[x]=ld[ch[x][0]]+ld[ch[x][1]]+(ty[x]==1);
        rd[x]=rd[ch[x][0]]+rd[ch[x][1]]+(ty[x]==-1);
        sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x];
    }
    //czqak//
    inline void add(int bg,int ed) {nxt[++ecnt]=head[bg];to[ecnt]=ed;head[bg]=ecnt;}
    inline void doit(int x,int v) {
        val[x]+=1ll*v*ty[x];
        sum[x]+=1ll*v*(ld[x]-rd[x]);
        tag[x]+=1ll*v;
    }
    inline void pushdown(int x) {
        if(tag[x]) {
            if(ch[x][0]) doit(ch[x][0],tag[x]);
            if(ch[x][1]) doit(ch[x][1],tag[x]);
            tag[x]=0;
        }
    }
    inline void rotate(int x) {
        int f=fa[x],ff=fa[f];
        bool tag=x==ch[fa[x]][1];
        ch[f][tag]=ch[x][tag^1];
        fa[ch[f][tag]]=f;
        ch[x][tag^1]=f;
        fa[f]=x;
        fa[x]=ff;
        if(ff) ch[ff][f==ch[ff][1]]=x;
        pushup(f);pushup(x);
    }
    void PUSHDOWN(int x) {if(fa[x]) PUSHDOWN(fa[x]);pushdown(x);}
    inline void splay(int x,int tar) {
        PUSHDOWN(x);
        for(int f;(f=fa[x])!=tar;rotate(x)) if(fa[f]!=tar) rotate((x==ch[fa[x]][1])==(f==ch[fa[f]][1])?f:x);
        if(!tar) rt=x;
    }
    int build(int l,int r,int f) {
        int mid=l+r>>1,x=mid;
        fa[x]=f;
        if(rnk[x]>0) val[x]=a[rnk[x]],ty[x]=1;else val[x]=-a[-rnk[x]],ty[x]=-1;
        if(l<mid)ch[x][0]=build(l,mid-1,x);
        if(mid<r)ch[x][1]=build(mid+1,r,x);
        pushup(x);
        return x;
    }
    inline int Nxt(){
        int x=ch[rt][1];    
        while(ch[x][0]) x=ch[x][0];
        return x;
    }
    inline int pre() {
        int x=ch[rt][0];
        while(ch[x][1]) x=ch[x][1];
        return x;
    }
    inline void split(int &x,int &y) {
        splay(x,0);x=pre();
        splay(y,0);y=Nxt();
        splay(x,0);splay(y,x);
    }
    inline void query(int x) {
        int a=dfn1[1],b=dfn1[x];
        split(a,b);
        printf("%lld
    ",sum[ch[b][0]]);
    }
    inline void change(int x,int f) {
        int a=dfn1[x],b=dfn2[x];
        split(a,b);
        int c=ch[b][0];
        ch[b][0]=fa[c]=0;
        pushup(b),pushup(a);
        a=dfn1[f];splay(a,0);
        b=Nxt();splay(b,a);
        ch[b][0]=c;fa[c]=b;
        pushup(b),pushup(a);
    }
    inline void addv(int x,int v) {
        int a=dfn1[x],b=dfn2[x];
        split(a,b);
        doit(ch[b][0],v);
    }
    void dfs(int x) {
        dfn1[x]=++tim;rnk[tim]=x;
        for(int i=head[x];i;i=nxt[i]) dfs(to[i]);
        dfn2[x]=++tim;rnk[tim]=-x;
    }
    int n;
    signed main() {
        n=read();
        for(int i=2;i<=n;i++) add(read(),i);
        for(int i=1;i<=n;i++) a[i]=read();
        tim=1;dfs(1);tim++;
        rt=build(1,tim,0);int m;
        m=read();
        char opt[10];int x,y,z;
        while(m--) {
            scanf("%s",opt);
            switch (opt[0]) {
                case 'Q': query(read());break;
                case 'C': x=read(),change(x,read());break;
                case 'F': x=read(),addv(x,read());break;
            }
        }
    }
    TLE
    我是咸鱼。转载博客请征得博主同意Orz
  • 相关阅读:
    python基础之列表的坑
    python基础之字典篇
    坦克大战[源码] 你懂得
    java例程练习(键盘事件)
    android基础(对话框风格Activity实现)
    android基础(Activity)
    android基础(开发环境搭建)
    android基础(android程序的后台运行问题)
    java(敲 七)
    java例程练习(匿名类用法)
  • 原文地址:https://www.cnblogs.com/sdfzhsz/p/9737198.html
Copyright © 2011-2022 走看看