bzoj 1180: [CROATIAN2009]OTOCI link cut tree

题意

给出n个点,要求资瓷若干操作:
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的路径上的点对应的权值的和。给出q个操作,要求在线处理所有操作。数据范围:1<=n<=30000, 1<=q<=300000, 0<=wi<=1000。

分析

裸的link cut tree,但在bzoj上面怎样都A不了……
数据要下来了在本地上面全部跑过,但交上去还是A不了……
跟黄学长的程序对拍了几千组都没出错,还是A不了……
无言以对
便只好假装AC了。

代码

#include
#include
#include
#include
#include
#include
#define N 300005
using namespace std;

int n,m,val[N];
struct tree{int l,r,val,fa,rev;}t[N];
stack <int> q;

void updata(int x)
{
    t[x].val=t[t[x].l].val+t[t[x].r].val+val[x];
}

void rttl(int x)  
{  
    int y=t[x].r;  
    t[x].r=t[y].l;  
    t[t[y].l].fa=x;  
    if (x==t[t[x].fa].l) t[t[x].fa].l=y;  
    else if (x==t[t[x].fa].r) t[t[x].fa].r=y;  
    t[y].fa=t[x].fa;  
    t[y].l=x;  
    t[x].fa=y;  
    updata(x);
    updata(y);
}  

void rttr(int x)  
{  
    int y=t[x].l;  
    t[x].l=t[y].r;  
    t[t[y].r].fa=x;  
    if (x==t[t[x].fa].l) t[t[x].fa].l=y;  
    else if (x==t[t[x].fa].r) t[t[x].fa].r=y;  
    t[y].fa=t[x].fa;  
    t[y].r=x;  
    t[x].fa=y;
    updata(x);
    updata(y);  
}  

bool isroot(int x)  
{  
    if (x!=t[t[x].fa].l&&x!=t[t[x].fa].r||!t[x].fa) return 1;  
    return 0;  
}  

void pushdown(int x)  
{  
    if (t[x].rev)  
    {  
        swap(t[x].l,t[x].r);  
        if (t[x].l) t[t[x].l].rev^=1;  
        if (t[x].r) t[t[x].r].rev^=1;  
        t[x].rev^=1;  
    }  
}  

void remove(int x)  
{  
    int y=x;  
    while (1)  
    {  
        q.push(y);  
        if (isroot(y)) break;  
        y=t[y].fa;  
    }  
    while (!q.empty())  
    {  
        int y=q.top();  
        q.pop();  
        pushdown(y);  
    }  
}  

void splay(int x)  
{  
    remove(x);  
    while (!isroot(x))  
    {  
        int p=t[x].fa,g=t[p].fa;  
        if (isroot(p))  
        {  
            if (x==t[p].l) rttr(p);  
            else rttl(p);  
            break;  
        }  
        if (x==t[p].l)  
        {  
            if (p==t[g].l)  
            {  
                rttr(g);rttr(p);  
            }else  
            {  
                rttr(p);rttl(g);  
            }  
        }else  
        {  
            if (p==t[g].r)  
            {  
                rttl(g);rttl(p);  
            }else  
            {  
                rttl(p);rttr(g);  
            }  
        }  
    }  
    updata(x);
}  

void access(int x)  
{  
    int y=0;  
    while (x)  
    {  
        splay(x);  
        t[x].r=y;  
        y=x;x=t[x].fa;  
    }  
}  

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

void cut(int x,int y)  
{  
    movetoroot(x);access(y);splay(y);t[y].l=0;t[x].fa=0;  
}  

void link(int x,int y)  
{  
    movetoroot(x);access(y);t[y].r=x;t[x].fa=y;splay(x);  
}  

int findroot(int x)  
{  
    access(x);splay(x);  
    while (t[x].l) x=t[x].l;  
    return x;  
}  
int query(int x,int y)
{
    movetoroot(x);access(y);splay(y);
    return t[y].val;
}

int main()
{
    freopen("otoci8.in","r",stdin);freopen("test.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&val[i]);
        t[i].val=val[i];
    }
    scanf("%d",&m);
    for (int i=1;i<=m;i++)
    {
        char ch[15];
        scanf("%s",ch);
        if (ch[0]=='b')
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if (findroot(x)==findroot(y)) printf("no\n");
            else
            {
                printf("%yes\n");
                link(x,y);
            }
        }else if (ch[0]=='p')
        {
            int x,y;
            scanf("%d%d",&x,&y);
            movetoroot(x);val[x]=y;updata(x);
        }else
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if (findroot(x)!=findroot(y)) printf("impossible\n");
            else printf("%d\n",query(x,y));
        }
    }
    return 0;
}

你可能感兴趣的:(link,cut,tree)