码迷,mamicode.com
首页 > 其他好文 > 详细

SPOJ GSS5 - Can you answer these queries V

时间:2018-10-31 00:05:37      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:std   技术分享   etc   oid   fine   testcase   stc   线段   names   

我又来水数据结构了。

按照套路,线段树上要维护四个值$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\n", 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

 

SPOJ GSS5 - Can you answer these queries V

标签:std   技术分享   etc   oid   fine   testcase   stc   线段   names   

原文地址:https://www.cnblogs.com/CzxingcHen/p/9880054.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!