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
  • 相关阅读:
    iOS通知的使用
    使用代理和block写一个alertView
    MongoDB的访问权限和用户设置
    编写高效SQL语句
    Linux 安装 jdk 环境
    基于3dsMax的地图编辑器设想
    入驻cnBlogs!
    毕设开发总结3D游戏框架及网络对战游戏的开发(1)
    gkENGINE 个人图形引擎展示
    利用D3DQUERY实现简单的GPU计时器
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9717269.html
Copyright © 2011-2022 走看看