[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\n",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\n",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
posted @ 2018-10-02 15:27  SWHsz  阅读(111)  评论(0编辑  收藏  举报