BZOJ3786: 星系探索

Posted ONION_CYC

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ3786: 星系探索相关的知识,希望对你有一定的参考价值。

【代码调试中】

技术分享图片
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
const int maxn=400010;
struct cyc{int l,r,rnd,sz,fa,delta,gnum,num,gsum,sum;}t[maxn];
struct edge{int v,from;}e[maxn];
int tote=0,first[maxn];
void insert(int u,int v){tote++;e[tote].v=v;e[tote].from=first[u];first[u]=tote;}
int n,m,be[maxn],ed[maxn],tot,a[maxn],b[maxn],c[maxn],st[maxn],root;
int read(){
    char c;int s=0,t=1;
    while(!isdigit(c=getchar()))if(c==-)t=-1;
    do{s=s*10+c-0;}while(isdigit(c=getchar()));
    return s*t;
}
void dfs(int x){
    be[x]=++tot;b[tot]=1;c[tot]=a[x];
    for(int i=first[x];i;i=e[i].from){
        dfs(e[i].v);
    }
    ed[x]=++tot;b[tot]=-1;c[tot]=a[x];
}
void up(int k){
    t[k].sz=1+t[t[k].l].sz+t[t[k].r].sz;
    t[k].gsum=t[k].gnum+t[t[k].l].gsum+t[t[k].r].gsum;
    t[k].sum=t[k].num+t[t[k].l].sum+t[t[k].r].sum;
    t[t[k].l].fa=t[t[k].r].fa=k;
}
void modify(int k,int x){t[k].num+=t[k].gnum*x;t[k].sum+=t[k].gsum*x;t[k].delta+=x;}
void down(int k){
    if(t[k].delta){
        modify(t[k].l,t[k].delta);modify(t[k].r,t[k].delta);
        t[k].delta=0;
    }
}
void DFS(int k){
    DFS(t[k].l);DFS(t[k].r);
    up(k);
}
void build(){
    int top=0;
    for(int i=1;i<=tot;i++){
        t[i]=(cyc){0,0,rand(),1,0,0,b[i],c[i],b[i],c[i]};
        while(top&&t[st[top]].rnd>t[i].rnd){
            t[st[top]].r=t[i].l;
            t[t[i].l].fa=st[top];t[st[top]].fa=i;
            t[i].l=st[top--];
        }
        t[st[top]].r=i;
        t[i].fa=st[top];
        st[++top]=i;
    }
    DFS(0);
    t[0]=(cyc){0,0,0,0,0,0,0,0,0};
    root=st[1];
    t[root].fa=0;
}
int find(int x){
    int sum=t[t[x].l].sz+1;
    while(t[x].fa!=0){
        if(t[t[x].fa].r==x)sum+=t[t[t[x].fa].l].sz+1;
        x=t[x].fa;
    }
    return sum;
}
int merge(int a,int b){
    if(!a||!b)return a^b;
    if(t[a].rnd<t[b].rnd){
        down(a);
        a=merge(t[a].r,b);
        up(a);
        return a;
    }
    else{
        down(b);
        merge(a,t[b].l);
        up(b);
        return b;
    }
}
void split(int k,int &l,int &r,int x){
    if(!k)return void(l=r=0);
    down(k);
    if(x<t[k].sz+1){
        r=k;
        split(t[k].l,l,t[k].l,x);
    }
    else{
        l=k;
        split(t[k].r,t[k].r,r,x-t[k].sz-1);
    }
    up(k);
}
int goroot(int x){
    int r=find(be[x]),a,b;
    split(root,a,b,r);
    r=t[a].sum;
    root=merge(a,b);
    return r;
}
void change(int x,int y){
    int a,b,c;
    split(root,b,c,find(ed[x]));
    split(b,a,b,find(be[x])-1);
    t[b].delta+=y;
    root=merge(a,b);
    root=merge(root,c);
}
void move(int x,int y){
    int a,b,c;
    split(root,b,c,find(ed[x]));
    split(b,a,b,find(be[x]-1));
    root=merge(a,c);
    t[b].fa=be[y];
    split(root,a,c,find(be[x]));
    root=merge(a,b);
    root=merge(root,c);
}
char s[10];
int main(){
    srand(233);
    n=read();
    for(int i=2;i<=n;i++)insert(read(),i);
    for(int i=1;i<=n;i++)a[i]=read();
    dfs(1);build();
    m=read();
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%s%d",s,&x);
        if(s[0]==Q){
            printf("%d\n",goroot(x));
        }
        if(s[0]==C){
            scanf("%d",&y);
            move(x,y);
        }
        if(s[0]==F){
            scanf("%d",&y);
            change(x,y);
        }
    }
    return 0;
}
View Code

 

以上是关于BZOJ3786: 星系探索的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ3786]星系探索(伪ETT)

BZOJ-3786星系探索 Splay + DFS序

Bzoj3786 星系探索

bzoj 3786 星系探索 dfs+splay

BZOJ3786星系探索 DFS序+Splay

bzoj3786星系探索