bzoj 1180: [CROATIAN2009]OTOCI

 动态树

/**************************************************************
    Problem: 1180
    User: lxy8584099
    Language: C++
    Result: Accepted
    Time:6400 ms
    Memory:2024 kb
****************************************************************/
 
/*
    再复习一下LCT
    就是一颗splay转来转去?
    分虚边和实边 
    虚边的意思是 改点没有连接到儿子  但是儿子连接到父亲 
    连接的时候连接成虚边 
    一个点最多有一个实边 虚边没有上限 
*/
 
#include<bits/stdc++.h>
#include<cstdio>
#define lc (c[x][0])
#define rc (c[x][1])
using namespace std;
const int N=30050;
int n,m,tot,sta[N],top;
int fa[N],c[N][2],sum[N],val[N]; bool turn[N];
void swap(int&a,int&b) {a^=b^=a^=b;} 
bool nroot(int x) {return c[fa[x]][0]==x||c[fa[x]][1]==x;} 
void pushup(int x) {sum[x]=sum[lc]+sum[rc]+val[x];} 
void pushdown(int x)
{
    if(!turn[x]) return; turn[x]=0,turn[lc]^=1,turn[rc]^=1;
    swap(c[lc][0],c[lc][1]),swap(c[rc][0],c[rc][1]);
}
void rotate(int x) // 旋转的时候注意虚边  
{
    int y=fa[x],z=fa[y],sx=c[y][1]==x,sy=c[z][1]==y,w=c[x][sx^1];
    if(nroot(y)) c[z][sy]=x; fa[x]=z; fa[w]=y; c[y][sx]=w;
    fa[y]=x; c[x][sx^1]=y; pushup(y); pushup(x); 
}
void splay(int x) // 先把x到nroot路径上的标记全排掉
// 这只是转到部分数的root,across之后才能转成全部树的root 
{
    int xx=x; sta[top=1]=xx; while(nroot(xx)) sta[++top]=xx=fa[xx]; 
    while(top) pushdown(sta[top--]); while(nroot(x))
    {
        int y=fa[x],z=fa[y]; if(nroot(y))
        rotate(((c[y][0]==x)^(c[z][0]==y))?x:y); rotate(x);
    }
}
void across(int x) {for(int y=0;x;x=fa[y=x]) splay(x),rc=y,pushup(x);} 
// 每次转了之后 默认上一次的x节点为右儿子(实边) 这样确保能打通! 
// 可以尝试强制为左儿子  
void mroot(int x) {across(x),splay(x),turn[x]^=1,swap(lc,rc);} 
// 因为强制右儿子 转上去后 一定是最深的 交换左右子树就变成最浅的了
int froot(int x) {across(x),splay(x);while(lc) x=lc;return x;} 
void link(int x,int y) {mroot(x);fa[x]=y;} 
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&val[i]),sum[i]=val[i];
    scanf("%d",&m); while(m--)
    {
        int x,y; char ch[10]; scanf("%s%d%d",ch,&x,&y);
        if(ch[0]=='b')
        {
            if(froot(x)==froot(y)) puts("no");
            else puts("yes"),link(x,y);
        }
        else if(ch[0]=='p') mroot(x),val[x]=y,pushup(x);
        else
        {
            if(froot(x)!=froot(y))  puts("impossible");
            else mroot(x),across(y),splay(y),printf("%d\n",sum[y]);
        }
    }
     
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lxy8584099/p/10331367.html