• luoguP4115 QTREE4 链分治


    具体看$qzc$论文吧......陈年老物了......

    主要注意每个链头一棵线段树而不是一棵全局线段树

    修改操作写完就是正确的,反而是初始化调了好一会......

    跑的还是很快的,有些地方没优化常数也还可以接受

    在$luogu$上把$Toptree$给卡下去了,现居$rank1$......

    代码的话....借鉴一下思想就行了

    实现就没有必要有些地方做得一样了

    #include <queue>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    extern inline char gc() {
        static char RR[23456], *S = RR + 23333, *T = RR + 23333;
        if(S == T) fread(RR, 1, 23333, stdin), S = RR;
        return *S ++;
    }
    inline int read() {
        int p = 0, w = 1; char c = gc();
        while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
        while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
        return p * w;
    }
    
    #define sid 100050
    #define eid 200050
    #define ri register int
    const int inf = 1e9;
    
    struct heap {
        priority_queue <int> f, g;
        inline void ins(int v) { if(v != -inf) f.push(v); } 
        inline void era(int v) { if(v != -inf) g.push(v); }
        inline int top() {
            while(1) {
                if(f.empty()) return -inf;
                if(g.empty()) return f.top();
                if(f.top() == g.top()) f.pop(), g.pop();
                else return f.top();
            }
        }
    } h[sid], ans;
    
    int n, m, wn, cnp;
    int cap[sid], nxt[eid], node[eid], fee[eid];
    inline void addeg(int u, int v, int w) {
        nxt[++ cnp] = cap[u]; cap[u] = cnp; node[cnp] = v; fee[cnp] = w;
        nxt[++ cnp] = cap[v]; cap[v] = cnp; node[cnp] = u; fee[cnp] = w;
    }
    
    #define cur node[i]
    int sz[sid], pre[sid], fa[sid], dep[sid];
    inline void dfs(int o) {
        sz[o] = 1;
        for(int i = cap[o]; i; i = nxt[i])
        if(cur != fa[o]) {
            fa[cur] = o; dep[cur] = dep[o] + fee[i]; dfs(cur);
            sz[o] += sz[cur]; if(sz[cur] > sz[pre[o]]) pre[o] = cur;
        }
    }
    
    int id, onp, col[sid];
    int anc[sid], len[sid], dfn[sid], ord[sid];
    inline void dfs(int o, int tp) {
        dfn[o] = ++ id; anc[o] = tp; ord[id] = o; len[tp] ++;
        if(!pre[o]) return; dfs(pre[o], tp);
        for(int i = cap[o]; i; i = nxt[i])
        if(cur != fa[o] && cur != pre[o]) dfs(cur, cur);
    }
    
    int tnp, rt[sid];
    struct seg { int l, r, v, ls, rs; } t[sid * 4];
    
    #define dis(x) dep[ord[x]] 
    inline void upd(int o, int l, int r) {
        int ls = t[o].ls, rs = t[o].rs, mid = (l + r) >> 1;
        t[o].l = max(t[ls].l, t[rs].l + dis(mid + 1) - dis(l));
        t[o].r = max(t[rs].r, t[ls].r + dis(r) - dis(mid));
        t[o].v = max(max(t[ls].v, t[rs].v), t[ls].r + t[rs].l + dis(mid + 1) - dis(mid));
    }
    
    inline void build(int &o, int l, int r) {
        if(!o) o = ++ onp;
        if(l == r) {
            int x = ord[l];
            for(ri i = cap[x]; i; i = nxt[i])
            if(cur != fa[x] && cur != pre[x]) h[x].ins(t[rt[cur]].l + dep[cur] - dep[x]);
            int d1 = h[x].top(); h[x].era(d1); int d2 = h[x].top(); h[x].ins(d1);
            t[o].l = t[o].r = max(d1, 0); t[o].v = max(0, max(d1, d1 + d2));
            return;
        }
        int mid = (l + r) >> 1;
        build(t[o].ls, l, mid);
        build(t[o].rs, mid + 1, r);
        upd(o, l, r);
    }
    
    inline void mdf(int o, int l, int r, int v, int s) {
        if(l == r) {
            if(v == s) {
                int d1 = h[v].top(); h[v].era(d1); int d2 = h[v].top(); h[v].ins(d1);
                if(col[v]) t[o].l = t[o].r = d1, t[o].v = d1 + d2;
                else t[o].l = t[o].r = max(d1, 0), t[o].v = max(0, max(d1, d1 + d2));
            }
            else {
                h[v].ins(t[rt[s]].l + dep[s] - dep[v]);
                int d1 = h[v].top(); h[v].era(d1); int d2 = h[v].top(); h[v].ins(d1);
                if(col[v]) t[o].l = t[o].r = d1, t[o].v = d1 + d2;
                else t[o].l = t[o].r = max(d1, 0), t[o].v = max(0, max(d1, d1 + d2));
            }
            return;
        }
        int mid = (l + r) >> 1;
        if(dfn[v] <= mid) mdf(t[o].ls, l, mid, v, s);
        else mdf(t[o].rs, mid + 1, r, v, s);
        upd(o, l, r);
    }
    
    int main() {
        wn = n = read();
        for(ri i = 1; i < n; i ++) {
            int u = read(), v = read();
            int w = read(); addeg(u, v, w);
        }
        dfs(1); dfs(1, 1); ans.ins(0);            
        for(ri i = n; i; i --) {
            int o = ord[i]; if(o != anc[o]) continue; 
            build(rt[o], dfn[o], dfn[o] + len[o] - 1);
            ans.ins(t[rt[o]].v);
        }
        m = read(); char opt = 0;
        for(ri i = 1; i <= m; i ++) {
            opt = gc();
            while(opt != 'C' && opt != 'A') opt = gc();
            if(opt == 'C') {
                int x = read(); col[x] ^= 1;
                if(col[x] == 0) wn ++; else wn --;
                for(ri o = x, p = o; o; o = fa[o]) {
                    int f = anc[o];
                    int p1 = t[rt[f]].v, d1 = t[rt[f]].l;
                    if(fa[f]) h[fa[f]].era(t[rt[f]].l + dep[f] - dep[fa[f]]);
                    mdf(rt[f], dfn[f], dfn[f] + len[f] - 1, o, p);
                    int p2 = t[rt[f]].v, d2 = t[rt[f]].l;
                    if(p1 != p2) ans.era(p1), ans.ins(p2);
                    p = o = f;
                }
            }
            else {
                if(wn == 0) printf("They have disappeared.
    ");
                else printf("%d
    ", ans.top());
            }
        }
        return 0;
    }
  • 相关阅读:
    C++小知识点
    C++类的const成员函数、默认的构造函数、复制形参调用函数
    原码、反码、补码,计算机中负数的表示
    linux学习笔记(一)
    涉及string、char *、char[ ]、逗号表达式 的代码
    软件皮肤 IrisSkin
    DataGridView 闪烁
    C# String StringBuider 解惑
    JTA事务总结
    世界真的存在吗
  • 原文地址:https://www.cnblogs.com/reverymoon/p/9499510.html
Copyright © 2020-2023  润新知