Quantcast
Channel: CSDN博客推荐文章
Viewing all articles
Browse latest Browse all 35570

BZOJ2959——长跑

$
0
0

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;
}
作者:qzh_1430586275 发表于2017/1/1 16:57:49 原文链接
阅读:36 评论:0 查看评论

Viewing all articles
Browse latest Browse all 35570


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>