【题解】 Luogu P4312 / SP4155 [COCI 2009] OTOCI / 极地旅行社

原题地址:P4312 [COCI 2009] OTOCI / 极地旅行社/SP4155 OTOCI - OTOCI

lct入门难度的题,十分弱智(小蒟蒻说lct是什么,能吃吗?)

bridge操作判联通,用find,不同的话link一下

penguins修改点权,把这个点旋转到树根暴力修改并pushup

excursion先判联通,如果联通输出点权之和

操作就是这样,简单有点像P2147 [SDOI2008]洞穴勘测

代码:

#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define N 300005
using namespace std;
inline int read()
{
    int f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
inline void Swap(register int &a,register int &b)
{
    a^=b^=a^=b;
}
int n,m,v[N];
struct Link_cut_tree{
    int top,c[N][2],fa[N],q[N],rev[N],sum[N];
    inline void pushup(register int x)
    {
        sum[x]=sum[c[x][0]]+sum[c[x][1]]+v[x];
    }
    inline void pushdown(int x)
    {
        int l=c[x][0],r=c[x][1];
        if(rev[x])
        {
            rev[l]^=1;
            rev[r]^=1;
            rev[x]^=1;
            Swap(c[x][0],c[x][1]);
        }
    }
    inline bool isroot(int x)
    {
        return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;
    }
    inline void rotate(int x)
    {
        int y=fa[x],z=fa[y],l,r;
        if(c[y][0]==x)
            l=0;
        else
            l=1;
        r=l^1;
        if(!isroot(y))
        {
            if(c[z][0]==y)
                c[z][0]=x;
            else
                c[z][1]=x;
        }
        fa[x]=z;
        fa[y]=x;
        fa[c[x][r]]=y;
        c[y][l]=c[x][r];
        c[x][r]=y;
        pushup(y);
        pushup(x);
    }
    inline void splay(int x)
    {
        top=1;
        q[top]=x;
        for(register int i=x;!isroot(i);i=fa[i])
            q[++top]=fa[i];
        for(register int i=top;i;--i)
            pushdown(q[i]);
        while(!isroot(x))
        {
            int y=fa[x],z=fa[y];
            if(!isroot(y))
            {
                if((c[y][0]==x)^(c[z][0]==y))
                    rotate(x);
                else
                    rotate(y);
            }
            rotate(x);
        }
        pushup(x);
    }
    inline void access(int x)
    {
        for(register int t=0;x;t=x,x=fa[x])
        {
            splay(x);
            c[x][1]=t;
            pushup(x);
        }
    }
    inline void makeroot(int x)
    {
        access(x);
        splay(x);
        rev[x]^=1;
    }
    inline int find(int x)
    {
        access(x);
        splay(x);
        while(c[x][0])
            x=c[x][0];
        return x;
    }
    inline void split(int x,int y)
    {
        makeroot(x);
        access(y);
        splay(y);
    }
    inline void cut(int x,int y)
    {
        split(x,y);
        if(c[y][0]==x)
        {
            c[y][0]=0;
            fa[x]=0;
        }
    }
    inline void link(int x,int y)
    {
        makeroot(x);
        fa[x]=y;
    }
}T;
int main()
{
    n=read();
    for(register int i=1;i<=n;++i)
    {
        v[i]=read();
        T.sum[i]=v[i];
    }
    m=read();
    while(m--)
    {
        char c[10];
        scanf("%s",c);
        int x=read(),y=read();
        if(c[0]=='b')
        {
            if(T.find(x)==T.find(y))
                puts("no");
            else
            {
                puts("yes");
                T.link(x,y);
            }
        }
        else if(c[0]=='p')
        {
            T.access(x);
            T.splay(x);
            v[x]=y;
            T.pushup(x);
        }
        else
        {
            if(T.find(x)!=T.find(y))
                puts("impossible");
            else
            {
                T.split(x,y);
                printf("%d\n",T.sum[y]);
            }
        }
    }
    return 0;
}

lct真简单

猜你喜欢

转载自www.cnblogs.com/yzhang-rp-inf/p/9652332.html
今日推荐