hdu 4010 Query on The Trees LCT

支持:
1.添加边 x,y
2.删边 x,y
3.对于路径x,y上的所有节点的值加上w
4.询问路径x,y上的所有节点的最大权值

分析:
裸的lct...
rev忘了清零死循环了两小时。。。

1:就是link操作

2:就是cut操作

3:维护多一个mx域,mx[x]表示在splay中以节点x为根的子树的最大点权,每次修改时,把x置为splay的根,打通y到x的路径,把y splay到根,那么,直接对y节点的lazy标记加上为w即可。

4:同3操作,把x置为splay的根,打通y到x的路径,把y splay到根,那么,y子树所对应的节点就是路径x到y的所有节点。

 

另外,题目貌似描述有点问题,不光是询问非法输出-1,是指操作如果是非法就输出-1....

#include <set>
#include <map>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

#define debug puts("here")
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
#define pb push_back
#define RD(n) scanf("%d",&n)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
#define All(vec) vec.begin(),vec.end()
#define MP make_pair
#define PII pair<int,int>
#define PQ priority_queue
#define cmax(x,y) x = max(x,y)
#define cmin(x,y) x = min(x,y)
#define Clear(x) memset(x,0,sizeof(x))
/*

#pragma comment(linker, "/STACK:1024000000,1024000000")

int size = 256 << 20; // 256MB
char *p = (char*)malloc(size) + size;
__asm__("movl %0, %%esp
" :: "r"(p) );

*/

/******** program ********************/

const int MAXN = 3e5+5;

// 外挂
char op;
inline void Int(int &x){
    while( !isdigit(op=getchar()) );
    x = op-'0';
    while(isdigit(op=getchar()))
        x = x*10+op-'0';
}

struct LCT{
    int ch[MAXN][2],fa[MAXN];
    int lz[MAXN],mx[MAXN],val[MAXN];
    bool rev[MAXN];
    int sta[MAXN],top;

    inline void init(){
        Clear(ch);
        Clear(fa);
        Clear(lz);
        Clear(rev);
        mx[0] = 0;
    }

    inline void modify(int x,int d){ // 单点增加lazy标记
        if(!x)return;
        lz[x] += d;
        mx[x] += d;
        val[x] += d;
    }

    inline void clear(int x){
        if(!x)return;
        if(rev[x]){
            if(ch[x][0])rev[ch[x][0]] ^= 1;
            if(ch[x][1])rev[ch[x][1]] ^= 1;
            swap(ch[x][0],ch[x][1]);
            rev[x] = 0;
        }
        if(lz[x]){
            modify(ch[x][0],lz[x]);
            modify(ch[x][1],lz[x]);
            lz[x] = 0;
        }
    }

    inline void update(int x){
        if(!x)return;
        mx[x] = max( val[x],max(mx[ch[x][0]],mx[ch[x][1]]) );
    }

    inline bool isRoot(int x){
        return !x || !( (ch[ fa[x] ][0]==x) || (ch[ fa[x] ][1]==x) );
    }

    inline bool sgn(int x){
        return ch[ fa[x] ][1]==x;
    }
    inline void setc(int y,int d,int x){
        ch[y][d] = x;
        fa[x] = y;
    }
    inline void rot(int x){
        int y = fa[x] , z = fa[y] , d = sgn(x)^1;
        setc(y,d^1,ch[x][d]);
        if(isRoot(y)) fa[x] = fa[y];
        else setc(z,sgn(y),x);
        setc(x,d,y);
        update(y);
    }

    inline void splay(int x){
        if(!x)return;
        top = 0;
        sta[++top] = x;
        for(int y=x;!isRoot(y);y=fa[y])
            sta[++top] = fa[y];
        while(top)clear(sta[top--]);

        while(!isRoot(x)){
            if(isRoot(fa[x]))rot(x);
            else{
                sgn(x)==sgn(fa[x]) ? rot(fa[x]) : rot(x);
                rot(x);
            }
        }
        update(x);
    }

    inline int access(int x){
        int y = 0;
        for(;x;x=fa[y = x]){
            splay(x);
            ch[x][1] = y;
            update(x);
        }
        return y;
    }

    inline void mRoot(int x){
        rev[ access(x) ] ^= 1;
        splay(x);
    }

    inline int getRoot(int x){
        x = access(x);
        while(ch[x][0]){
            x = ch[x][0];
            clear(x);
        }
        return x;
    }

    inline bool jud(int x,int y){// ok
        return getRoot(x)==getRoot(y);
    }

    inline void link(int x,int y){
        if(jud(x,y)){
            puts("-1");
            return;
        }
        mRoot(x);
        fa[x] = y;
        //access(x);
    }

    inline void cut(int x,int y){
        if(x==y||!jud(x,y)){
            puts("-1");
            return;
        }
        mRoot(x);
        access(y);
        splay(y);
        fa[ ch[y][0] ] = 0;
        ch[y][0] = 0;
        update(y);
    }

    inline void modify(int x,int y,int c){
        if(!jud(x,y)){
            puts("-1");
            return;
        }
        mRoot(x);
        access(y);
        splay(y);
        modify(y,c);
        clear(y);
    }

    inline int ask(int x,int y){
        if(!jud(x,y))
            return -1;
        mRoot(x);
        access(y);
        splay(y);
        return mx[y];
    }

}lct;

struct Edge{
    int y,next;
}edge[MAXN<<1];

int po[MAXN],tol;

inline void add(int x,int y){
    edge[++tol].y = y;
    edge[tol].next = po[x];
    po[x] = tol;
}

void dfs(int x,int pa){
    lct.fa[x] = pa;
    for(int i=po[x];i;i=edge[i].next)
        if(edge[i].y!=pa)
            dfs(edge[i].y,x);
}

int main(){

#ifndef ONLINE_JUDGE
    freopen("sum.in","r",stdin);
    //freopen("sum.out","w",stdout);
#endif

    int x,y,w,n,m,op;
    while(~RD(n)){
        lct.init();
        Clear(po);
        tol = 0;

        REP(i,2,n){
            Int(x);Int(y);
            add(x,y);
            add(y,x);
        }

        dfs(1,0);

        rep1(i,n){
            RD(lct.val[i]);
            lct.mx[i] = lct.val[i];
        }
        RD(m);
        while(m--){
            Int(op);
            if(op==1){
                Int(x);Int(y);
                lct.link(x,y);
            }else if(op==2){
                Int(x);Int(y);
                lct.cut(x,y);
            }else if(op==3){
                Int(w);Int(x);Int(y);
                lct.modify(x,y,w);
            }else{
                Int(x);Int(y);
                printf("%d
",lct.ask(x,y));
            }
        }
        puts("");
    }

    return 0;
}

  

原文地址:https://www.cnblogs.com/yejinru/p/3300206.html