首页 > 其他 > 详细

CF603EPastoral Oddities

时间:2019-03-13 18:21:07      阅读:158      评论:0      收藏:0      [点我收藏+]
/*
LCT管子题(说的就是你 水管局长)

首先能得到一个结论, 那就是当且仅当所有联通块都是偶数时存在构造方案

LCT动态加边, 维护最小生成联通块, 用set维护可以删除的边, 假如现在删除后不影响全都是偶数大小的性质 就删除


不清楚link为啥要makeroot两次 

*/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<set>
#include<cmath>
#define ll long long
#define M 400010
#define mmp make_pair
using namespace std;
int read() {
    int nm = 0, f = 1;
    char c = getchar();
    for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    return nm * f;
}
int n, m, cnt, ln[M], rn[M];

struct LCT {
    int fa[M], ch[M][2], sz[M], rev[M], val[M], mx[M], pl[M], zz[M];
#define ls ch[x][0]
#define rs ch[x][1]
    void pushup(int x) {
        sz[x] = sz[ls] + sz[rs] + zz[x] + 1;
        mx[x] = max(mx[ls], mx[rs]);
        pl[x] = (mx[x] == mx[ls]) ? pl[ls]: pl[rs];
        if(val[x] > mx[x]) mx[x] = val[x], pl[x] = x;
    }

    bool isr(int x) {
        return ch[fa[x]][0] != x && ch[fa[x]][1] != x;
    }

    void add(int x) {
        rev[x] ^= 1;
        swap(ls, rs);
    }

    void pushdown(int x) {
        if(rev[x]) {
            add(ls), add(rs);
            rev[x] = 0;
        }
    }

    void pd(int x) {
        if(!isr(x)) pd(fa[x]);
        pushdown(x);
    }

    void rotate(int x) {
        int y = fa[x], q = fa[y];
        bool dy = (ch[y][1] == x), dz = (ch[q][1] == y);
        if(!isr(y)) ch[q][dz] = x;
        fa[x] = q;
        fa[ch[x][dy ^ 1]] = y;
        ch[y][dy] = ch[x][dy ^ 1];
        ch[x][dy ^ 1] = y;
        fa[y] = x;
        pushup(y);
        pushup(x);
    }

    void splay(int x) {
        pd(x);
        while(!isr(x)) {
            int y = fa[x];
            if(!isr(y)) {
                int q = fa[y];
                if((ch[y][1] == x) ^ (ch[q][1] == y)) rotate(x);
                else rotate(y);
            }
            rotate(x);
        }
    }

    void access(int x) {
        for(int y = 0; x; y = x, x = fa[x]) splay(x), zz[x] += sz[rs] - sz[y], rs = y, pushup(x);
    }

    void maker(int x) {
        access(x);
        splay(x);
        add(x);
    }

    int findr(int x) {
        access(x);
        splay(x);
        while(ls) pushdown(x), x = ls;
        return x;
    }

    void link(int x, int y) {
        maker(x);
        maker(y);
        fa[x] = y;
        zz[y] += sz[x];
        sz[y] += sz[x];
    }

    void split(int x, int y) {
        maker(x), access(y), splay(y);
    }

    void cut(int x, int y) {
        split(x, y);
        if(fa[x] != y && ch[x][1]) return;
        fa[x] = ch[y][0] = 0;
        pushup(y);
    }

    int query(int x, int y) {
        split(x, y);
        return pl[y];
    }

    int sum(int x) {
        maker(x);
        return ((sz[x] + 1) >> 1) & 1;
    }


} lct;
set<pair<int, int> >st;
set<pair<int, int> >::reverse_iterator it;
int main() {
    n = read(), m = read();
    cnt = n;
//  for(int i = 1; i <= n; i++) lct.sz[i] = 1;
    for(int i = 1; i <= m; i++) {
        int vi = read(), vj = read();
        ln[i + n] = vi, rn[i + n] = vj;
        int x = read();
        lct.val[i + n] = x;
        lct.pushup(i + n);
        if(lct.findr(vi) != lct.findr(vj)) {
            if(lct.sum(vi)) cnt--;
            if(lct.sum(vj)) cnt--;
            lct.link(vi, i + n);
            lct.link(i + n, vj);
            lct.split(vi, vj);
            if(lct.sum(vj)) cnt++;
        } else {
            int pl = lct.query(vi, vj);
            if(lct.val[pl] <= x) {
                if(cnt == 0) printf("%d\n", st.rbegin()->first);
                else puts("-1");
                continue;
            }
            lct.cut(ln[pl], pl);
            lct.cut(rn[pl], pl);
            lct.link(vi, i + n);
            lct.link(i + n, vj);
            //  lct.split(vi, vj);
            st.erase(st.find(mmp(lct.val[pl], pl)));
        }
        st.insert(mmp(x, i + n));
        if(cnt) {
            puts("-1");
            continue;
        }
        while(1) {
            it = st.rbegin();
            int id = it->second;
            lct.cut(ln[id], id);
            lct.cut(id, rn[id]);
            if(lct.sum(ln[id]) || lct.sum(rn[id])) {
                lct.link(ln[id], id);
                lct.link(id, rn[id]);
                break;
            }
            st.erase(*it);
        }
        printf("%d\n", st.rbegin()->first);
    }
    return 0;
}


CF603EPastoral Oddities

原文:https://www.cnblogs.com/luoyibujue/p/10524803.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!