zoukankan      html  css  js  c++  java
  • SPOJ GSS5

    我又来水数据结构了。

    按照套路,线段树上要维护四个值$res, sum, suf, pre$,分别表示当前区间的最大子段和,总和,强制选右端点的最大子段和,强制选左端点的最大子段和,那么更新的时候就有:

        inline void up(int p) {
            sum(p) = sum(lc) + sum(rc);     
            suf(p) = max(suf(rc), sum(rc) + suf(lc)); 
            pre(p) = max(pre(lc), sum(lc) + pre(rc));
            res(p) = max(res(lc), res(rc), suf(lc) + pre(rc));
        }

    注意查询的时候返回空结点的$suf,pre,res$都是$-inf$。

    如果询问$xa, ya, xb, yb$满足$ya < xb$,那么答案就为$sum(ya, xb) + max(0, suf(xa, ya - 1)) + max(0, pre(xb + 1, yb))$;如果不满足,那么答案在$res(xb, ya)$、$pre(ya + 1, yb) + suf(xb, ya)$、$pre(xb, ya) + suf(xa, xb - 1)$、$sum(xb, ya) + max(0, suf(xa, xb - 1)) + max(0, pre(ya + 1, yb))$取个最大。

    画个图理解一下就好啦。

    时间复杂度为$O(Tnlogn)$,虽然常数很大,但是跑个$10000$完全没问题。

    Code:

    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int N = 1e4 + 5;
    const int inf = 1 << 30;
    
    int testCase, n, qn, a[N];
    
    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 int max(int x, int y) {
        return x > y ? x : y;
    }
    
    inline int max(int x, int y, int z) {
        return max(x, max(y, z));
    }
    
    inline void chkMax(int &x, int y) {
        if(y > x) x = y;
    }
    
    namespace SegT {
        struct Node {
            int lc, rc, res, suf, pre, sum;
    
            inline void init() {
                res = suf = pre = -inf, sum = 0;
            }
    
        } s[N << 2];
    
        #define lc p << 1
        #define rc p << 1 | 1
        #define res(p) s[p].res
        #define suf(p) s[p].suf
        #define pre(p) s[p].pre
        #define sum(p) s[p].sum
        #define mid ((l + r) >> 1)
    
        inline void up(int p) {
            sum(p) = sum(lc) + sum(rc);     
            suf(p) = max(suf(rc), sum(rc) + suf(lc)); 
            pre(p) = max(pre(lc), sum(lc) + pre(rc));
            res(p) = max(res(lc), res(rc), suf(lc) + pre(rc));
        }
    
        void build(int p, int l, int r) {
            if(l == r) {
                sum(p) = res(p) = suf(p) = pre(p) = a[l];
                return;
            }
    
            build(lc, l, mid);
            build(rc, mid + 1, r);
            up(p);
        }
    
        Node query(int p, int l, int r, int x, int y) {
            if(x > y) return (Node) {0, 0, -inf, -inf, -inf, 0};
            if(x <= l && y >= r) return s[p];
    
            Node ln, rn, res;
            ln.init(), rn.init(), res.init();
    
            if(x <= mid) ln = query(lc, l, mid, x, y);
            if(y > mid) rn = query(rc, mid + 1, r, x, y);
    
            res.sum = ln.sum + rn.sum;
            res.suf = max(rn.suf, ln.suf + rn.sum);
            res.pre = max(ln.pre, rn.pre + ln.sum);
            res.res = max(ln.res, rn.res, ln.suf + rn.pre);
    
            return res;
        }
    
    } using namespace SegT;
    
    inline void solve(int xa, int ya, int xb, int yb) {
        int res;
        if(ya < xb) {
            res = query(1, 1, n, ya, xb).sum;
            res += max(0, query(1, 1, n, xa, ya - 1).suf);
            res += max(0, query(1, 1, n, xb + 1, yb).pre);
        } else {
            res = query(1, 1, n, xb, ya).res;
            chkMax(res, query(1, 1, n, ya + 1, yb).pre + query(1, 1, n, xb, ya).suf);
            chkMax(res, query(1, 1, n, xa, xb - 1).suf + query(1, 1, n, xb, ya).pre);
            chkMax(res, query(1, 1, n, xb, ya).sum + max(0, query(1, 1, n, xa, xb - 1).suf) + max(0, query(1, 1, n, ya + 1, yb).pre));
        }
    
        printf("%d
    ", res);
    }
    
    int main() {
        for(read(testCase); testCase--; ) {
            read(n);
            for(int i = 1; i <= n; i++) read(a[i]);
    
            build(1, 1, n);
    
            read(qn);
            for(int xa, ya, xb, yb; qn--; ) {
                read(xa), read(ya), read(xb), read(yb);
                solve(xa, ya, xb, yb);
            }
    
        }
        return 0;
    }
    View Code
  • 相关阅读:
    两种图像缩放算法的对比与实现
    字节流与字符流
    自己的网站 首都易搜网 又修改了一下。。首页改变了
    序列化和反序列化 .NET
    关于 C#异步方法的使用
    vs2010 设计视图中控件无法加载,提示未将对象设置到对象的实例。
    .Net 中的反射(查看基本类型信息) Part.2
    URL重写
    .Net 中的反射(序章) Part.1
    数据库死锁问题 及 解决方法
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9880054.html
Copyright © 2011-2022 走看看