• luoguP3250 [HNOI2016]网络 树链剖分 + 堆


    机房某大佬告诉我,一条链在全局线段树中的区间最多有$log$段

    因此同样的,代表不在这条链上的区间同样只有$log$段

    对这$log$段区间进行维护即可

    为了能够删除,在线段树的每个节点暴力维护一个堆

    每次加入一条链时,在这$log$段区间上暴力加入元素

    每次删除一条链时,暴力删除元素

    询问时,对所有经过的区间进行查询

    注意堆标记不要下传,直接标记永久化就行

    插入 / 删除复杂度单次$O(log^3 n)$

    查询复杂度单次$O(log n)$

    空间复杂度$O(n log^2 n)$

    注:$bzoj$会$MLE$....不要轻易尝试

    注2:打了30多min,好累啊.....

    注3:大家还是去学习$O(n log n)$的优秀做法吧...

    #include <map>
    #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 ri register int
    #define sid 200050
    
    int n, m, cnp, id;
    int nxt[sid], node[sid], cap[sid];
    
    inline void addedge(int u, int v) {
        nxt[++ cnp] = cap[u]; cap[u] = cnp; node[cnp] = v;
        nxt[++ cnp] = cap[v]; cap[v] = cnp; node[cnp] = u;
    }
    
    int U[sid], V[sid], W[sid];
    int dfn[sid], sz[sid], dep[sid];
    int son[sid], anc[sid], fa[sid];
    
    #define cur node[i]
    void dfs(int o) {
        sz[o] = 1;
        for(int  i = cap[o]; i; i = nxt[i])
        if(cur != fa[o]) {
            dep[cur] = dep[o] + 1; fa[cur] = o; dfs(cur); sz[o] += sz[cur];
            if(sz[cur] > sz[son[o]]) son[o] = cur;
        }
    }
    
    void dfs(int o, int ac) {
        dfn[o] = ++ id; anc[o] = ac;
        if(!son[o]) return; dfs(son[o], ac);
        for(int i = cap[o]; i; i = nxt[i])
        if(cur != fa[o] && cur != son[o]) dfs(cur, cur);
    }
    
    struct Heap {
        priority_queue <int> q1, q2;
        inline void ins(int x) { q1.push(x); }
        inline void era(int x) { q2.push(x); }
        inline int top() {
            while(1) {
                if(q2.empty()) return q1.top();
                if(q1.top() == q2.top()) q1.pop(), q2.pop();
                else return q1.top();
            }
        }
    } t[sid << 1];
    
    #define ls (o << 1)
    #define rs (o << 1 | 1)
    
    void build(int o, int l, int r) {
        t[o].ins(-1); if(l == r) return;
        int mid = (l + r) >> 1;
        build(ls, l, mid); build(rs, mid + 1, r); 
    }
    
    void upd(int o, int l, int r, int ml, int mr, int v, int opt) {
        if(ml > mr) return;
        if(ml > r || mr < l) return;
        if(ml <= l && mr >= r) { if(opt) t[o].ins(v); else t[o].era(v); return; }
        int mid = (l + r) >> 1;
        upd(ls, l, mid, ml, mr, v, opt);
        upd(rs, mid + 1, r, ml, mr, v, opt);
    }
    
    int qry(int o, int l, int r, int ml, int mr) {
        if(ml > r || mr < l) return -1;
        if(ml <= l && mr >= r) return t[o].top();
        int mid = (l + r) >> 1;
        return max(t[o].top(), max(qry(ls, l, mid, ml, mr), qry(rs, mid + 1, r, ml, mr)));
    }
    
    struct Seg { 
        int l, r; 
        friend bool operator < (Seg a, Seg b)
        { return a.l < b.l; }
    }; vector <Seg> re;
    
    void Upd(int u, int v, int w, int opt) {
        re.clear(); 
        int pu = anc[u], pv = anc[v];
        while(pu != pv) {
            if(dep[pu] < dep[pv]) swap(u, v), swap(pu, pv);
            re.push_back( { dfn[pu], dfn[u] } ); 
            u = fa[pu]; pu = anc[u];
        } 
        if(dep[u] < dep[v]) swap(u, v);
        re.push_back( { dfn[v], dfn[u] } );
        re.push_back( { 0, 0 } ); 
        re.push_back( { n + 1, n + 1 } );
        sort(re.begin(), re.end());
        for(ri i = 1; i < re.size(); i ++)
        upd(1, 1, n, re[i - 1].r + 1, re[i].l - 1, w, opt);
    }
    
    int main() {
        n = read(); m = read();
        for(ri i = 1; i < n; i ++) {
            int u = read(), v = read();
            addedge(u, v);
        }
        dfs(1); dfs(1, 1); build(1, 1, n);
        for(ri i = 1; i <= m; i ++) {
            int opt = read(), u, v, w;
            if(opt == 0) {
                u = read(); v = read(); w = read();
                U[i] = u; V[i] = v; W[i] = w; Upd(u, v, w, 1);
            }
            if(opt == 1) u = read(), Upd(U[u], V[u], W[u], 0);
            if(opt == 2) u = read(), printf("%d
    ", qry(1, 1, n, dfn[u], dfn[u]));
        }
        return 0;
    }
  • 相关阅读:
    java.util.logging.Logger使用详解
    JAVA7新增的对自动关闭资源的try语句的问题
    java的"1"+"asd"的底层
    oracle的存储过程与函数
    java.exe和javaw.exe有什么区别?
    需要看的知识点
    关于String-StringBuffer-Stringbuilder的知识点
    tomcat是什么?
    生产系统总结
    less
  • 原文地址:https://www.cnblogs.com/reverymoon/p/9559779.html
Copyright © 2020-2023  润新知