【BZOJ2843&&1180】极地旅行社,LCT练习

传送门-P2843
(1180是权限题,所以就不放了)
写在前面:为什么BZOJ上LCT好多都是权限题(╯‵□′)╯︵┻━┻
思路:判断联通用findroot函数(洞穴探测里已经说过了);修改x的操作可以把x旋转到所在的splay的根上来,再修改;查询的话把x,y分别access到同一棵splay上,splay操作后求值即可
注意:无
代码:

#include<bits/stdc++.h>
#define pd(i) (i>='0'&&i<='9')
using namespace std;
int n,m,x,y;
int stacks[30010];
char s[10];
struct tree
{
    int fa,ch[2],sum,data;
    bool lazy;
}a[200010];
int in()
{
    int t=0;
    char ch=getchar();
    while (!pd(ch)) ch=getchar();
    while (pd(ch)) t=(t<<3)+(t<<1)+ch-'0',ch=getchar();
    return t;
}
void ct(int x)
{
    a[x].sum=a[a[x].ch[0]].sum+a[a[x].ch[1]].sum+a[x].data;
}
#define isroot(x) (a[a[x].fa].ch[0]!=x&&a[a[x].fa].ch[1]!=x)
void pushdown(int x)
{
    if (!a[x].lazy) return;
    a[a[x].ch[0]].lazy^=1;
    a[a[x].ch[1]].lazy^=1;
    swap(a[x].ch[0],a[x].ch[1]);
    a[x].lazy=0;
}
void rorate(int x,bool mk)
{
    int y=a[x].fa;
    a[x].fa=a[y].fa;
    if (!isroot(y))
    {
        if (a[a[y].fa].ch[0]==y) a[a[y].fa].ch[0]=x;
        else a[a[y].fa].ch[1]=x;
    }
    a[y].ch[!mk]=a[x].ch[mk];
    a[a[x].ch[mk]].fa=y;
    a[x].ch[mk]=y;
    a[y].fa=x;
    ct(y);ct(x);
}
void splay(int x)
{
    int y,cnt=0,k=x;
    stacks[++cnt]=k;
    while (!isroot(k)) k=a[k].fa,stacks[++cnt]=k;
    for (int i=cnt;i;i--) pushdown(stacks[i]);
    while (!isroot(x))
    {
        y=a[x].fa;
        if (isroot(y))
        {
            if (a[y].ch[0]==x) rorate(x,1);
            else rorate(x,0);
        }
        else if (a[a[y].fa].ch[0]==y)
        {
            if (a[y].ch[0]==x) rorate(y,1);
            else rorate(x,0);
            rorate(x,1);
        }
        else
        {
            if (a[y].ch[1]==x) rorate(y,0);
            else rorate(x,1);
            rorate(x,0);
        }
    }
}
void access(int x)
{
    for (int y=0;x;y=x,x=a[x].fa)
        splay(x),
        a[x].ch[1]=y,
        ct(x);
}
void link(int x,int y)
{
    access(x);
    splay(x);
    a[x].lazy^=1;
    a[x].fa=y;
}
void cut(int x,int y)
{
    access(x);
    splay(x);
    a[x].lazy^=1;
    access(y);
    splay(y);
    a[x].fa=a[y].ch[0]=0;
    ct(y);
}
int findroot(int x)
{
    access(x);
    splay(x);
    while (a[x].ch[0]) x=a[x].ch[0];
    return x;
}
main()
{
    n=in();
    for (int i=1;i<=n;i++)
        a[i].data=in(),
        a[i].sum=a[i].data;
    scanf("%d",&m);
    while (m--)
    {
        scanf("%s",s);
        x=in();y=in();
        if (s[0]=='b')
        {
            if (findroot(x)==findroot(y)) puts("no");
            else puts("yes"),link(x,y);
        }
        else if (s[0]=='p')
        {
            splay(x);
            a[x].sum+=(y-a[x].data);
            a[x].data=y;
        }
        else
        {
            if (findroot(x)!=findroot(y)) puts("impossible");
            else
                access(x),
                splay(x),
                a[x].lazy^=1,
                access(y),
                splay(y),
                printf("%d\n",a[y].sum);
        }
    }
}

你可能感兴趣的:(【BZOJ2843&&1180】极地旅行社,LCT练习)