zoukankan      html  css  js  c++  java
  • SPOJ GSS7

    板的不能再板,链剖+线段树或者是LCT随便维护。

    感觉唯一要注意的是跳链的时候要对$x$向上跳和$y$向上跳的情况分开讨论,而不能直接$swap$,因为只有两段接触的端点才能相互合并,而且每一次向上跳的线段要放在已经合并完成之后的左端。

    最后输出答案的时候要注意这时候$x$和$y$合并好的树链上其实左端点都是在上面的,而$x$和$y$其实是左端点相接触的,所以最后合并的时候$x.lmax + y.lmax$可能成为最优答案而不是$x.rmax + y.lmax$。

    一开始线段树写手残了……

    时间复杂度$O(nlog^2n)$。

    Code:

    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int N = 1e5 + 5;
    
    int n, qn, tot = 0, head[N], a[N], w[N];
    int dfsc = 0, id[N], siz[N], dep[N], son[N], fa[N], top[N]; 
    
    struct Edge {
        int to, nxt;
    } e[N << 1];
    
    inline void add(int from, int to) {
        e[++tot].to = to;
        e[tot].nxt = head[from];
        head[from] = tot;
    }
    
    inline void read(int &X) {
        X = 0; char ch = 0; int op = 1;
        for(; ch > '9' || ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }    
    
    inline void swap(int &x, int &y) {
        int t = x; x = y; y = t;
    }
    
    inline int max(int x, int y) {
        return x > y ? x : y;
    }
    
    inline int max(int x, int y, int z) {
        return max(max(x, y), z);
    }
    
    void dfs1(int x, int fat, int depth) {
        dep[x] = depth, fa[x] = fat, siz[x] = 1;
        int maxson = -1;
        for(int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(y == fat) continue;
            dfs1(y, x, depth + 1);
    
            siz[x] += siz[y];
            if(siz[y] > maxson) 
                maxson = siz[y], son[x] = y;
        }
    }
    
    void dfs2(int x, int topf) {
        top[x] = topf, w[id[x] = ++dfsc] = a[x];
        if(!son[x]) return;
        dfs2(son[x], topf);
        for(int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(y == fa[x] || y == son[x]) continue;
            dfs2(y, y);
        }
    }    
    
    struct Node {
        int lmax, rmax, sum, res, val;
        bool tag;
    
        inline void init() {
               lmax = rmax = sum = res = val = 0;
            tag = 0;
        }
    
    };
    
    inline Node merge(Node x, Node y) {
        Node ans; ans.init();
        ans.sum = x.sum + y.sum;
        ans.lmax = max(x.lmax, x.sum + y.lmax);
        ans.rmax = max(y.rmax, y.sum + x.rmax);
        ans.res = max(x.res, y.res, x.rmax + y.lmax);
        return ans;
    }
    
    namespace SegT {
        Node s[N << 2];
    
        #define lc p << 1
        #define rc p << 1 | 1
        #define mid ((l + r) >> 1)
        #define lmax(p) s[p].lmax
        #define rmax(p) s[p].rmax
        #define sum(p) s[p].sum
        #define res(p) s[p].res
        #define tag(p) s[p].tag
        #define val(p) s[p].val
    
        inline void up(int p) {
            if(!p) return;
            lmax(p) = max(lmax(lc), sum(lc) + lmax(rc));
            rmax(p) = max(rmax(rc), sum(rc) + rmax(lc));
            sum(p) = sum(lc) + sum(rc);
            res(p) = max(res(lc), res(rc), rmax(lc) + lmax(rc));
        }
    
        inline void down(int p, int l, int r) {
            if(!tag(p)) return;
            sum(lc) = (mid - l + 1) * val(p), sum(rc) = (r - mid) * val(p);
            res(lc) = lmax(lc) = rmax(lc) = max(0, val(p) * (mid - l + 1));
            res(rc) = lmax(rc) = rmax(rc) = max(0, val(p) * (r - mid));
            val(lc) = val(rc) = val(p);
            tag(lc) = tag(rc) = 1, tag(p) = 0;
        }
    
        void build(int p, int l, int r) {
            s[p].init();
            if(l == r) {
                sum(p) = w[l];
                lmax(p) = rmax(p) = res(p) = max(0, w[l]);
                return;
            }
    
            build(lc, l, mid);
            build(rc, mid + 1, r);
            up(p);
        }
    
        void modify(int p, int l, int r, int x, int y, int v) {
            if(x <= l && y >= r) {
                sum(p) = (r - l + 1) * v;
                lmax(p) = rmax(p) = res(p) = max(0, sum(p));
                tag(p) = 1, val(p) = v;
                return;
            }
    
            down(p, l, r);
            if(x <= mid) modify(lc, l, mid, x, y, v);
            if(y > mid) modify(rc, mid + 1, r, x, y, v);
            up(p);
        }
    
    /*    Node query(int p, int l, int r, int x, int y) {
            if(x <= l && y >= r) return s[p];
    
            down(p, l, r);
    
            if(y <= mid) return query(lc, l, mid, x, y);
            if(x > mid) return query(rc, mid + 1, r, x, y);
    
            Node res, ln = query(lc, l, mid, x, mid), rn = query(rc, mid + 1, y, mid + 1, y);
            res.init();
    
            res.sum = ln.sum + rn.sum;
            res.lmax = max(ln.lmax, ln.sum + rn.lmax);
            res.rmax = max(rn.rmax, rn.sum + ln.rmax);
            res.res = max(ln.res, rn.res, ln.rmax + rn.lmax);
    
            return res;
        }    */
        
        Node query(int p, int l, int r, int x, int y) {
            if(x <= l && y >= r) return s[p];
            
            down(p, l, r);
            
            Node ln, rn, ans; 
            ln.init(), rn.init(), ans.init();
            
            if(x <= mid) ln = query(lc, l, mid, x, y);
            if(y > mid) rn = query(rc, mid + 1, r, x, y);
            
            ans = merge(ln, rn);
            return ans; 
        }
    
    } using namespace SegT;
    
    inline void mTree(int x, int y, int v) {
        for(; top[x] != top[y]; ) {
            if(dep[top[x]] < dep[top[y]]) swap(x, y);
            modify(1, 1, n, id[top[x]], id[x], v);
            x = fa[top[x]];
        }
        if(dep[x] > dep[y]) swap(x, y);
        modify(1, 1, n, id[x], id[y], v);
    }
    
    inline void qTree(int x, int y) {
        Node ln, rn; ln.init(), rn.init(); 
        for(; top[x] != top[y]; ) {
            if(dep[top[x]] > dep[top[y]]) 
                ln = merge(query(1, 1, n, id[top[x]], id[x]), ln), x = fa[top[x]];
            else 
                rn = merge(query(1, 1, n, id[top[y]], id[y]), rn), y = fa[top[y]];
        }
        if(dep[x] > dep[y]) 
            ln = merge(query(1, 1, n, id[y], id[x]), ln);
        else 
            rn = merge(query(1, 1, n, id[x], id[y]), rn);
    
        printf("%d
    ", max(ln.res, rn.res, ln.lmax + rn.lmax));
    }
    
    int main() {
        read(n);
        for(int i = 1; i <= n; i++) read(a[i]);
        for(int x, y, i = 1; i < n; i++) {
            read(x), read(y);
            add(x, y), add(y, x);
        }
    
        dfs1(1, 0, 1), dfs2(1, 1);
        build(1, 1, n);
    
        read(qn);
        for(int op, x, y; qn--; ) {
            read(op), read(x), read(y);
            if(op == 2) {
                int v; read(v);
                mTree(x, y, v);
            } else qTree(x, y);
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    智慧养老民政监管平台建设方案
    CF600E Lomsat gelral dsu on tree
    dsu on tree详解
    【Spring 从0开始】Spring5 新功能,整合日志框架 Log4j2
    【Spring 从0开始】JdbcTemplate 数据库事务管理
    【Spring 从0开始】JdbcTemplate 数据库事务参数
    【Spring 从0开始】JdbcTemplate 数据库事务管理
    【Spring 从0开始】JdbcTemplate 操作数据库
    【Spring 从0开始】AOP 操作
    【Spring 从0开始】AOP 操作中的相关术语、环境准备
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9717269.html
Copyright © 2011-2022 走看看