HDU 4010 Query on The Trees [2011 大连网络赛]

#include <memory.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <iostream>
#include <stdio.h>
#include <stack>
#include <time.h>
using namespace std;
#define M(a) memset(a,0,sizeof(a))
typedef pair<int,int> PII;
const int N = 300000+5;
const int INF = -100000000;
typedef __int64 LL;
int max(int x,int y)
{
    return x > y ? x : y;
}

class LinkCutTree
{
public:
    int ch[N][2],fa[N],pp[N],SZ[N];//path parent
    int Max[N],cost[N],lazy[N];
    int rev[N];
    int find_root(int cur)
    {
        while(fa[cur])cur = fa[cur];
        return cur;
    }
    void Modify(int x,int k)//修改
    {
        if(x == 0) return;
        cost[x] = cost[x] + k;
        Max[x] = Max[x] + k;
        lazy[x] = lazy[x] + k;
    }
    void Spread(int x)//伸展

    {
        if(x == 0) return;
        if(lazy[x] != 0)
        {
            Modify(ch[x][0],lazy[x]);
            Modify(ch[x][1],lazy[x]);
            lazy[x] = 0;
        }
        if(rev[x] != 0)
        {
            if(ch[x][0] != 0) rev[ch[x][0]] ^=1;
            if(ch[x][1] != 0) rev[ch[x][1]] ^=1;
            swap(ch[x][0],ch[x][1]);
            rev[x] = 0;
        }
    }
    void update(int x)//更新
    {
        Max[x] = max(cost[x],max(Max[ch[x][0]],Max[ch[x][1]]));
        return;
    }
    void rotate(int x,bool f)//旋转
    {
        int y = fa[x];
        ch[y][!f] = ch[x][f];
        fa[ch[x][f]] = y;
        fa[x] = fa[y];
        if(fa[x])ch[fa[y]][ch[fa[y]][1] == y] = x;
        ch[x][f] = y;
        fa[y] = x;
        update(y);
    }
    void splay(int x)//
    {
        Spread(x);
        int i1,i2,root = find_root(x);
        if (root == x) return;
        pp[x] = pp[root];
        pp[root] = 0;
        while(fa[x])
        {
            if(!fa[fa[x]])
            {
                Spread(fa[x]);
                Spread(x);
                rotate(x,ch[fa[x]][0] == x);
            }
            else
            {
                int y = fa[x],z = fa[y];
                Spread(z);
                Spread(y);
                Spread(x);
                int f = (ch[z][0] == y);
                if(ch[y][f] == x)
                {
                    rotate(x,!f);
                    rotate(x,f);
                }
                else
                {
                    rotate(y,f);
                    rotate(x,f);
                }
            }
        }
        update(x);
    }
    //void Rev(int x) {rev[x] ^= 1;return;}
    void access(int x)//
    {
        for(int pre = 0; x;)
        {
            splay(x);
            fa[ch[x][1]] = 0;
            pp[ch[x][1]] = x;
            ch[x][1] = pre;
            pp[pre] = 0;
            fa[pre] = x;
            pre = x;
            update(x);
            x = pp[x];
        }
    }
    int paint_path(int a,int b,int c)//
    {
        if(a > b) swap(a,b);
        access(a);
        int ans = 0;
        for(int pre = 0; b;)
        {
            splay(b);
            if(pp[b] == 0)
            {
                Modify(pre,c);
                Modify(ch[b][1],c);
                cost[b] += c;
                update(b);
            }
            fa[ch[b][1]] = 0;
            pp[ch[b][1]] = b;
            ch[b][1] = pre;
            pp[pre] = 0;
            fa[pre] = b;
            pre = b;
            update(b);
            b = pp[b];
        }
        return ans;
    }
    int query_path(int a,int b)//
    {
        if(a > b) swap(a,b);
        access(a);
        int ans = 0;
        for(int pre = 0; b;)
        {
            splay(b);
            if(pp[b] == 0)
            {
                ans = max(cost[b],max(Max[ch[b][1]],Max[pre]));
            }
            fa[ch[b][1]] = 0;
            pp[ch[b][1]] = b;
            ch[b][1] = pre;
            pp[pre] = 0;
            fa[pre] = b;
            pre = b;
            update(b);
            b = pp[b];
        }
        return ans;
    }
    int get_root(int x)//
    {
        access(x);
        splay(x);
        while(ch[x][0])
            x = ch[x][0];
        return x;
    }
    void cut(int x,int y)//
    {
        if(x == y) return;
        access(x);
        splay(x);
        rev[x] ^=1;
        access(y);
        splay(y);
        pp[ch[y][0]] = pp[y];
        fa[ch[y][0]] = 0;
        pp[y] = 0;
        ch[y][0] = 0;
        update(y);
    }
    void join(int x,int y)//
    {
        access(x);
        splay(x);
        rev[x] ^=1;
        access(y);
        splay(y);
        rev[y] ^=1;
        pp[x] = y;
        return;
    }
    void init()
    {
        M(ch),M(fa);
        M(lazy);
        M(rev);
        pp[0] = 0;
        Max[0] = 0;
        rev[0] = 0;
        lazy[0] = 0;
    }
} LCT;

struct Edge
{
    int p,next;
} E[3 * N];

int head[N],cnt = 0;

void Init()
{
    memset(head,-1,sizeof(head));
    cnt = 0;
}

void add(int a,int b)
{
    cnt++;
    E[cnt].p = b;
    E[cnt].next = head[a];
    head[a] = cnt;
    cnt++;
    E[cnt].p = a;
    E[cnt].next = head[b];
    head[b] = cnt;
}

int S[N],sidx;
int ins[N];

void dfs()
{
    int i,j,k;
    memset(ins,0,sizeof(ins));
    sidx = 0;
    S[++sidx] = 1;
    LCT.pp[1] = 0;
    while(sidx > 0)
    {
        int cur = S[sidx];
        if(ins[cur] == 0)
        {
            ins[cur] = 1;
            for(i = head[cur]; i != -1; i = E[i].next)
            {
                int p = E[i].p;
                if(ins[p] == 0)
                {
                    LCT.pp[p] = cur;
                    S[++sidx] = p;
                }
            }
        }
        else
        {
            sidx--;
            ins[cur] = 0;
        }
    }
}

inline int Scan()
{
    int res = 0 , ch ;
    while( !( ( ch = getchar() ) >= '0' && ch <= '9' ) )
    {
        if( ch == EOF )  return 1 << 30 ;
    }
    res = ch - '0' ;
    while( ( ch = getchar() ) >= '0' && ch <= '9' )
        res = res * 10 + ( ch - '0' ) ;
    return res ;
}

int main()
{
    int i,j,k;
    int n;
    while(scanf("%d",&n) != EOF)
    {
        LCT.init();
        Init();
        for(i = 1; i < n; i++)
        {
            int a,b;
            a = Scan();
            b = Scan();
            add(a,b);
        }
        int tmp;
        for(i = 1; i <= n; i++)
        {
            tmp = Scan();
            LCT.cost[i] = tmp;
            LCT.Max[i] = LCT.cost[i];
        }
        dfs();
        int Q;
        Q = Scan();
        int cmd,w,x,y;
        for(i = 1; i <= Q; i++)
        {
            cmd = Scan();
            if(cmd == 1)
            {
                //scanf("%d %d",&x,&y);
                x = Scan();
                y = Scan();
                if(LCT.get_root(x) != LCT.get_root(y))
                    LCT.join(x,y);
                else printf("-1\n");
            }
            else if(cmd == 2)
            {
                //scanf("%d %d",&x,&y);
                x = Scan();
                y = Scan();
                if(x != y && LCT.get_root(x) == LCT.get_root(y))
                    LCT.cut(x,y);
                else printf("-1\n");
            }
            else if(cmd == 3)
            {
                //scanf("%d %d %d",&w,&x,&y);
                w = Scan();
                x = Scan();
                y = Scan();
                if(LCT.get_root(x) == LCT.get_root(y))
                {
                    LCT.paint_path(x,y,w);
                }
                else printf("-1\n");
            }
            else
            {
                //scanf("%d %d",&x,&y);
                x = Scan();
                y = Scan();
                if(LCT.get_root(x) == LCT.get_root(y))
                    printf("%d\n",LCT.query_path(x,y));
                else printf("-1\n");
            }
        }
        printf("\n");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值