BZOJ2959——长跑

来源:互联网 发布:淘宝客佣金分成 编辑:程序博客网 时间:2024/04/25 18:23

1、题意:n个点,m个操作,3种操作,链接某两个点,修改某个点的权值,询问两点之间最大权路径(如果某个点在路径中两次,那么只计算一次的值)
2、分析:先来考虑那个最大路径是什么鬼。。一个环里面的点那么这个点都可以到对吧。。那就是缩环咯,这样就可以搞成一个树,缩环用并查集来做,每一次链接两个点,如果变成环就缩,不是就在树上玩,那么这个很显然可以使用lct+并查集来完成。

#include <map>#include <set>#include <stack>#include <cmath>#include <queue>#include <vector>#include <bitset>#include <string>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define M 1000010#define LL long long#define MOD 1000000007#define inf 2147483647#define llinf 4000000000000000000ll#define For(i, x, y) for(int i = (x); i < (y); i ++)#define rep(i, x, y) for(int i = (x); i <= (y); i ++)#define drep(i, x, y) for(int i = (x); i >= (y); i --)inline int read(){    char ch=getchar();int x=0,f=1;    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}inline LL llread(){    char ch=getchar();LL x=0,f=1;    while(ch<'0'||ch    >'9'){if(ch=='-')f=-1;ch=getchar();}    while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}struct Union{    int fa[M];    inline void init(int n){        rep(i, 1, n) fa[i] = i;    }    inline int find(int x){        return fa[x] == x ? x : fa[x] = find(fa[x]);    }    inline void merge(int x, int y){        int p = find(x), q = find(y);        if(p != q) fa[p] = q;    }} aa, bb;namespace LinkCutTree{    struct Node{        Node *ch[2], *fa;        int val, sum, num;        bool rev;        Node();        inline int which();        inline void reverse(){            if(this){                rev ^= 1;                swap(ch[0], ch[1]);            }        }        inline void pd(){            if(rev){                ch[0] -> reverse();                ch[1] -> reverse();                rev = 0;            }        }        inline void maintain(){            sum = ch[0] -> sum + ch[1] -> sum + val;        }    } *null, *pos[M], tree[M];    inline int Node::which(){        if(fa == null || (fa -> ch[0] != this && fa -> ch[1] != this)) return -1;        return fa -> ch[1] == this;    }    Node::Node(){        rev = false;        ch[0] = ch[1] = fa = null;        sum = val = num = 0;    }    inline void rotate(Node *o){        Node *p = o -> fa;        int l = o -> which(), r = l ^ 1;        o -> fa = p -> fa;        if(p -> which() != -1) p -> fa -> ch[p -> which()] = o;        p -> ch[l] = o -> ch[r];        if(o -> ch[r]) o -> ch[r] -> fa = p;        o -> ch[r] = p; p -> fa = o;        o -> ch[r] -> maintain();        o -> maintain();    }    inline void splay(Node *o){        static stack<Node*> st;        Node *p = o;        while(1){            st.push(p);            if(p -> which() == -1) break;            p = p -> fa;        }        while(!st.empty()){            st.top() -> pd(); st.pop();        }        while(o -> which() != -1){            p = o -> fa;            if(p -> which() != -1){                if(p -> which() ^ o -> which()) rotate(o);                else rotate(p);            }            rotate(o);        }    }    inline void Access(Node *o){        Node *y = null;        while(o != null){            splay(o);            o -> ch[1] = y;            o -> maintain();            y = o;            o -> fa = pos[bb.find(o -> fa -> num)];            o = o -> fa;        }    }    inline void MovetoRoot(Node *o){        Access(o);        splay(o);        o -> reverse();    }    inline void Link(Node *x, Node *y){        MovetoRoot(x);        x -> fa = y;    }    inline void Cut(Node *x, Node *y){        MovetoRoot(x);        Access(y);        splay(y);        y -> ch[0] = x -> fa = null;        y -> maintain();    }    inline void color(Node* &a, int b){        if(a == null) return;        if(a -> num != b){            pos[b] -> val += a -> val;                //a -> val = 0;        }        bb.merge(a -> num, b);        color(a -> ch[0], b);        color(a -> ch[1], b);        a -> maintain();        //a = null;    }}int value[M]; int main(){    //freopen("0input.in", "r", stdin);    using namespace LinkCutTree;    pos[0] = null = &tree[0];    int n = read(), m = read();    aa.init(n); bb.init(n);    rep(i, 0, n){        tree[i].ch[0] = null;        tree[i].ch[1] = null;        tree[i].fa = null;    }    rep(i, 1, n){        pos[i] = &tree[i];         value[i] = pos[i] -> val = read();        pos[i] -> maintain();         pos[i] -> num = i;     }    while(m --){        int p = read(), a = read(), b = read();        if(p == 1){            a = bb.find(a), b = bb.find(b);            if(aa.find(a) == aa.find(b)){                if(a == b) continue;                MovetoRoot(pos[b]);                Access(pos[a]);                splay(pos[a]);                color(pos[a], a);            }            else{        //      puts("-1");                Link(pos[a], pos[b]);                aa.merge(a, b);             }        }        else if(p == 2){            int x = bb.find(a);            splay(pos[x]);            pos[x] -> val += b - value[a];            pos[x] -> maintain();            value[a] = b;        }        else{            a = bb.find(a), b = bb.find(b);            if(aa.find(a) != aa.find(b)){                puts("-1"); continue;            }             MovetoRoot(pos[b]);            Access(pos[a]);            splay(pos[a]);            printf("%d\n", pos[a] -> sum);        }    }    return 0;}
0 0