LA 3938 动态最大连续区间 线段树

思路很清晰,实现很繁琐。分析过程可以参考LRJ,自己的总结晚些放。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxN=5e5+5,maxNode=1e6+5;
#define ll long long
#define Seg pair<int,int>
#define fi first
#define se second

#define lson l,m,rt*2
#define rson m+1,r,rt*2+1

ll prefix_sum[maxN];
ll sum(int L, int R) {return prefix_sum[R] - prefix_sum[L - 1];}
ll sum(Seg p) {return sum(p.fi, p.se);}
Seg better(Seg a, Seg b) {
    if (sum(a) !=  sum(b)) return sum(a) > sum(b) ? a : b;
    else return a < b ? a : b;
}

int qL, qR;

struct SegTree {
    int max_prefix[maxNode];
    int max_suffix[maxNode];
    Seg max_sub[maxNode];

    void build(int l, int r, int rt) {
        if (l == r) {
            max_prefix[rt] = max_suffix[rt] = l;
            max_sub[rt] = make_pair(l, l);
            return;
        }
        int m = l + (r - l) / 2;
        int lch = rt * 2, rch = rt * 2 + 1;
        build(lson);
        build(rson);

        // push_up
        // 递推max_prefix
        ll v1 = sum(l, max_prefix[lch]);
        ll v2 = sum(l, max_prefix[rch]);
        if (v1 == v2) max_prefix[rt] = min(max_prefix[lch], max_prefix[rch]);
        else max_prefix[rt] = v1 > v2 ? max_prefix[lch] : max_prefix[rch];

        // 递推max_suffix
        v1 = sum(max_suffix[lch], r);
        v2 = sum(max_suffix[rch], r);
        if (v1 == v2) max_suffix[rt] = min(max_suffix[lch], max_suffix[rch]);
        else max_suffix[rt] = v1 > v2 ? max_suffix[lch] : max_suffix[rch];

        // 递推max_sub
        max_sub[rt] = better(max_sub[lch], max_sub[rch]);
        max_sub[rt] = better(max_sub[rt], make_pair(max_suffix[lch], max_prefix[rch]));
    }
    
    Seg query_prefix(int l, int r, int rt) {
        if (max_prefix[rt] <= qR) return make_pair(l, max_prefix[rt]);
        int m = (l + r) / 2;
        int lch = rt * 2;
        if (qR <= m) return query_prefix(lson);
        Seg i = query_prefix(rson);
        i.fi = l;
        return better(i, make_pair(l, max_prefix[lch]));
    }
    Seg query_suffix(int l, int r, int rt) {
        if (max_suffix[rt] >= qL) return make_pair(max_suffix[rt], r);
        int m = (l + r) / 2;
        int rch = 2 * rt + 1;
        if (qL > m) return query_suffix(rson);
        Seg i = query_suffix(lson);
        i.se = r;
        return better(i, make_pair(max_suffix[rch], r));
    }
    Seg query(int l, int r, int rt) {
        if (qL <= l && r <= qR) return max_sub[rt];
        int m = (l + r) / 2;
        if (qR <= m) return query(lson);
        if (qL > m) return query(rson);
        Seg i1 = query_prefix(rson);
        Seg i2 = query_suffix(lson);
        Seg i3 = better(query(lson), query(rson));
        return better(make_pair(i2.fi, i1.se), i3);
    }
};

SegTree tree;

int main() {
    // freopen("data.in", "r", stdin);
    int kase = 0, n, a, Q;
    while (~scanf("%d%d", &n, &Q)) {
        prefix_sum[0] = 0;
        for (int i = 0; i < n; ++i) {
            scanf("%d", &a);
            prefix_sum[i + 1] = prefix_sum[i] + a;
        }
        tree.build(1, n, 1);
        printf("Case %d:\n", ++kase);
        while (Q--) {
            int L, R;
            scanf("%d%d", &L, &R);
            qL = L, qR = R;
            Seg ans = tree.query(1, n, 1);
            printf("%d %d\n", ans.fi, ans.se);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Rosebud/p/9545713.html