bzoj2843 极地旅行社

来源:互联网 发布:linux快捷键退出终端 编辑:程序博客网 时间:2024/06/08 19:44

【题意】

n个点,m个操作,共4种:

1.x和y连边

2.查询x和y是否连通

3.修改x的点权

4.查询x到y路径点权和

【数据范围】

n<=30000,m<=100000

【思路】

LCT模板题。

【时间复杂度】

O(m log n)

#include<cstdio>#include<cstring>#include<algorithm>#define N 30010using namespace std; int n, m, x, y, fa[N], ch[N][2], rev[N], size[N], sum[N], a[N], isroot[N];char S[20]; inline int read(){    int x=0, f=1; char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}    return x*f;} void updateRev(int i){    if(!i)return;    swap(ch[i][0], ch[i][1]); rev[i]^=1;}void pushdownRev(int i){    if(!rev[i])return;    updateRev(ch[i][0]); updateRev(ch[i][1]);    rev[i]=0;}void update(int i){    size[i]=size[ch[i][0]]+size[ch[i][1]]+1;    sum[i]=sum[ch[i][0]]+sum[ch[i][1]]+a[i];}void P(int x){    if(!isroot[x])P(fa[x]);    pushdownRev(x);}void rotate(int x){    int y=fa[x], kind=ch[y][1]==x;    ch[y][kind]=ch[x][!kind];    if(ch[x][!kind])fa[ch[x][!kind]]=y;    ch[x][!kind]=y;    fa[x]=fa[y];    if(isroot[y]){isroot[x]=1; isroot[y]=0;}    else ch[fa[y]][ch[fa[y]][1]==y]=x;    fa[y]=x;    update(y);}void splay(int x){    P(x);    while(!isroot[x]){        int f=fa[x], ff=fa[f];        if(!isroot[f]){            if((ch[f][0]==x)==(ch[ff][0]==f)){rotate(f); rotate(x);}            else{rotate(x); rotate(x);}        }else rotate(x);    }    update(x);} void access(int x){    int y=0;    while(x){        splay(x);        isroot[ch[x][1]]=1;        ch[x][1]=y; isroot[y]=0;        update(x);        y=x; x=fa[x];    }}void memroot(int x){    access(x); splay(x); updateRev(x);}int find(int x, int y){    memroot(x); access(y); splay(y);    int x1=y; while(ch[x1][0])x1=ch[x1][0];    return x1==x;}void link(int x, int y){    memroot(x); fa[x]=y;}void ins(int x, int y){    memroot(x); a[x]=y; sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+a[x];}int check(int x, int y){    memroot(x); access(y); splay(y);    return sum[y];} int main(){    n=read();    for(int i=1; i<=n; i++)a[i]=read(); m=read();    for(int i=1; i<=n; i++){        ch[i][0]=ch[i][1]=fa[i]=rev[i]=0;        isroot[i]=size[i]=1; sum[i]=a[i];    }    for(int i=1; i<=m; i++){        scanf("%s", S+1); x=read(); y=read();        if(S[1]=='b'){            if(!find(x, y)){printf("yes\n"); link(x, y);}            else printf("no\n");        }        if(S[1]=='p')ins(x, y);        if(S[1]=='e'){            if(find(x, y))printf("%d\n", check(x, y));            else printf("impossible\n");        }    }    return 0;}


0 0
原创粉丝点击