bzoj1180 [CROATIAN2009]OTOCI LCT

Description


给出n个结点以及每个点初始时对应的权值wi。起始时点与点之间没有连边。有3类操作:
1、bridge A B:询问结点A与结点B是否连通。
如果是则输出“no”。否则输出“yes”,并且在结点A和结点B之间连一条无向边。
2、penguins A X:将结点A对应的权值wA修改为X。
3、excursion A B:如果结点A和结点B不连通,则输出“impossible”。
否则输出结点A到结点B的路径上的点对应的权值的和。

数据范围:1<=n<=30000, 1<=q<=300000, 0<=wi<=1000。

Solution


非常naive的LCT裸题
做这个主要是想说明一个问题,link(x,y)的时候既可以在xy之间连一条虚边,也可以瞎jb操作然后连实边
LCT真是太神奇辣

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)

const int N=600005;

struct treeNode {int son[2],fa,sum,v; bool rev,is_root;} t[N];

int fa[N];

void push_up(int x) {
    t[x].sum=t[x].v;
    if (t[x].son[0]) t[x].sum+=t[t[x].son[0]].sum;
    if (t[x].son[1]) t[x].sum+=t[t[x].son[1]].sum;
}

void push_down(int x) {
    if (!x||!t[x].rev) return ;
    std:: swap(t[x].son[0],t[x].son[1]);
    t[t[x].son[0]].rev^=1;
    t[t[x].son[1]].rev^=1;
    t[x].rev=0;
}

void remove(int x) {
    if (!t[x].is_root) remove(t[x].fa);
    push_down(x);
}

void rotate(int x) {
    if (t[x].is_root) return ;
    int y=t[x].fa; int z=t[y].fa;
    int k=t[y].son[1]==x;
    t[y].son[k]=t[x].son[!k];
    if (t[x].son[!k]) t[t[x].son[!k]].fa=y;
    t[x].son[!k]=y; t[y].fa=x;
    t[x].fa=z;
    if (t[y].is_root) {
        t[x].is_root=1;
        t[y].is_root=0;
    } else t[z].son[t[z].son[1]==y]=x;
    push_up(y); push_up(x);
}

void splay(int x) {
    remove(x);
    while (!t[x].is_root) {
        int y=t[x].fa; int z=t[y].fa;
        if (!t[y].is_root) {
            if ((t[z].son[1]==y)^(t[y].son[1]==x)) rotate(x);
            rotate(y);
        }
        rotate(x);
    }
}

void access(int x) {
    int y=0;
    do {
        splay(x);
        t[t[x].son[1]].is_root=1;
        t[t[x].son[1]=y].is_root=0;
        push_up(x);
        y=x; x=t[x].fa;
    } while (x);
}

void mroot(int x) {
    access(x); splay(x); t[x].rev^=1;
}

void link(int x,int y) {
    //mroot(x); t[x].fa=y;
    mroot(x); access(y); t[x].fa=y; t[y].son[1]=x;
    t[x].is_root=0;
    splay(x);
}

void cut(int x,int y) {
    mroot(x); access(y); splay(y);
    t[y].son[1]=t[x].fa=0;
    t[x].is_root=1;
    push_up(y);
}

int get_father(int x) {
    if (!fa[x]) return x;
    return fa[x]=get_father(fa[x]);
}

int main(void) {
    int n; scanf("%d",&n);
    rep(i,1,n) {
        scanf("%d",&t[i].v);
        t[i].sum=t[i].v;
        t[i].is_root=1;
    }
    int m; scanf("%d",&m);
    while (m--) {
        char opt[11]; scanf("%s",opt);
        int x,y; scanf("%d%d",&x,&y);
        if (opt[0]=='b') {
            if (get_father(x)==get_father(y)) puts("no");
            else {
                puts("yes");
                link(x,y);
                fa[get_father(x)]=get_father(y);
            }
        } else if (opt[0]=='p') {
            mroot(x); t[x].v=y; push_up(x);
        } else {
            if (get_father(x)!=get_father(y)) {
                puts("impossible");
                continue;
            } else {
                mroot(x); access(y); splay(y);
                printf("%d\n", t[y].sum);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jpwang8/article/details/80042704
LCT