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

来源:互联网 发布:linux rpm 路径 编辑:程序博客网 时间:2024/05/27 14:13
#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;}