hdu 4010 Query on The Trees

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4010

题目描述:输入一棵树,然后有4种操作

1. 连接 a b  2. 断开 a b 3.给a 到 b的路径上每个点增加一个值 w 4.查询 a到 b路径上的最大值

解题思路:动态树(LCT)本题几乎完全按照kuangbin大神的博客上的思路写的,没办法,本弱刚刚学lct,掌握不好,尤其是不会处理 a到 b的路径问题,有一个小小的思路,最终证明也是正确的。求 u和 v的LCA,先Access(v),也就是打通根到v的这条链。然后就类似Access(u)的过程,注意只是类似。就是不断地向上找 u到根的链,一旦发现某条链的father已经为空(也就是说这棵树的根一定在这条链上!!)那么这时的那个点就是LCA(u,v)

就如下图,Access(v)之后,红色的边就是preferred edge,也就是维护在splay里面的边


下面就是类似Access(u)一样,从 u向上找,直到找到lca(详见代码)

再次感谢kuangbin巨巨

//#pragma comment(linker,"/STACK:102400000,102400000")
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define ll long long
#define db double
#define PB push_back
#define lson k<<1
#define rson k<<1|1
using namespace std;

const int N = 300005;
const int INF = 2000000000;

int ch[N][2],pre[N],key[N];
int add[N],rev[N],Max[N];
bool rt[N];

void update_add(int r,int d)
{
    if(!r) return;
    key[r]+=d,add[r]+=d,Max[r]+=d;
}

void update_rev(int r)
{
    if(!r) return;
    swap(ch[r][0],ch[r][1]);
    rev[r]^=1;
}

void push_down(int r)
{
    if(add[r])
    {
        update_add(ch[r][0],add[r]);
        update_add(ch[r][1],add[r]);
        add[r]=0;
    }
    if(rev[r])
    {
        update_rev(ch[r][0]),update_rev(ch[r][1]);
        rev[r]=0;
    }
}

void push_up(int r)
{
    Max[r]=max(max(Max[ch[r][0]],Max[ch[r][1]]),key[r]);
}

void rotate(int x)
{
    int y=pre[x],d=ch[y][1]==x;
    ch[y][d]=ch[x][!d],pre[ch[y][d]]=y;
    pre[x]=pre[y],pre[y]=x;
    ch[x][!d]=y;
    if(rt[y]) rt[y]=false,rt[x]=true;
    else ch[pre[x]][ch[pre[x]][1]==y]=x;
    push_up(y);
}

void P(int r)
{
    if(!rt[r]) P(pre[r]);
    push_down(r);
}

void Splay(int r)
{
    P(r);
    while(!rt[r])
    {
        int f=pre[r],ff=pre[f];
        if(rt[f]) rotate(r);
        else if((ch[ff][1]==f)==(ch[f][1]==r))
            rotate(f),rotate(r);
        else rotate(r),rotate(r);
    }
    push_up(r);
}

int Access(int x)
{
    int y=0;
    for(;x;x=pre[y=x])
    {
        Splay(x);
        rt[ch[x][1]]=true,rt[ch[x][1]=y]=false;
        push_up(x);
    }
    return y;
}

bool judge(int u,int v)
{
    while(pre[u]) u=pre[u];
    while(pre[v]) v=pre[v];
    return u==v;
}

void mroot(int r)
{
    Access(r);
    Splay(r);
    update_rev(r);
}

void lca(int &u,int &v)
{
    Access(v),v=0;
    while(u)
    {
        Splay(u);
        if(!pre[u]) return;
        rt[ch[u][1]]=true;
        rt[ch[u][1]=v]=false;
        push_up(u);
        u=pre[v=u];
    }
}

void link(int u,int v)
{
    if(judge(u,v))
    {
        puts("-1");
        return;
    }
    mroot(u);
    pre[u]=v;
}

void cut(int u,int v)
{
    if(u==v||!judge(u,v))
    {
        puts("-1");
        return;
    }
    mroot(u);
    Splay(v);
    pre[ch[v][0]]=pre[v];
    rt[ch[v][0]]=true;
    pre[v]=ch[v][0]=0;
    push_up(v);
}

void ADD(int u,int v,int w)
{
    if(!judge(u,v))
    {
        puts("-1");
        return;
    }
    lca(u,v);
    update_add(ch[u][1],w),update_add(v,w);
    key[u]+=w;
    push_up(u);
}

void query(int u,int v)
{
    if(!judge(u,v))
    {
        puts("-1");
        return;
    }
    lca(u,v);
    printf("%d\n",max(max(Max[ch[u][1]],Max[v]),key[u]));
}

int head[N],to[N<<1],next[N<<1],nedge;

void add_edge(int a,int b)
{
    to[nedge]=b,next[nedge]=head[a],head[a]=nedge++;
}

void dfs(int k)
{
    for(int i=head[k];i>=0;i=next[i])
    {
        if(pre[to[i]]!=0) continue;
        pre[to[i]]=k;
        dfs(to[i]);
    }
}

void getint(int &x)
{
    char c=getchar();
    while(!(c>='0'&&c<='9')) c=getchar();
    x=c-'0';
    while((c=getchar())>='0'&&c<='9') x=x*10+c-'0';
}

int main()
{
#ifdef PKWV
    freopen("in.in","r",stdin);
#endif // PKWV
    int n,q;
    while(scanf("%d",&n)+1)
    {
        for(int i=0;i<=n;i++)
        {
            ch[i][0]=ch[i][1]=0;
            pre[i]=0,head[i]=-1;
            add[i]=0,rev[i]=0,rt[i]=true;
        }
        nedge=0;
        Max[0]=-INF;
        for(int i=1;i<n;i++)
        {
            int u,v;
            getint(u),getint(v);
            add_edge(u,v),add_edge(v,u);
        }
        for(int i=1;i<=n;i++)
        {
            getint(key[i]);
            Max[i]=key[i];
        }
        pre[1]=-1;
        dfs(1);
        pre[1]=0;
        getint(q);
        while(q--)
        {
            int op;
            getint(op);
            int x,y;
            if(op==1)
            {
                getint(x),getint(y);
                link(x,y);
            }else if(op==2)
            {
                getint(x),getint(y);
                cut(x,y);
            }else if(op==3)
            {
                int w;
                getint(w),getint(x),getint(y);
                ADD(x,y,w);
            }else
            {
                getint(x),getint(y);
                query(x,y);
            }
        }
        puts("");
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/u014076176/article/details/39741119
今日推荐