题意:动态最大连续子序列和,静态的题目
分析:nlogn的归并思想。线段树维护结点的三个信息,最大前缀和,最大后缀和,该区间的最大和的两个端点,然后答案是三个的better。书上用pair保存端点,用自带的<来得到最优。
#include <bits/stdc++.h> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; typedef pair<int, int> P; const int N = 5e5 + 5; ll sum[N]; struct ST { int pre[N<<2], suf[N<<2]; P sub[N<<2]; ll get_sum(P p) { return sum[p.second] - sum[p.first-1]; } P better(P a, P b) { ll v1 = get_sum (a), v2 = get_sum (b); if (v1 != v2) return v1 > v2 ? a : b; else return a < b ? a : b; } void push_up(int l, int r, int rt) { pre[rt] = better (make_pair (l, pre[rt<<1]), make_pair (l, pre[rt<<1|1])).second; //该区间的最大前缀 suf[rt] = better (make_pair (suf[rt<<1], r), make_pair (suf[rt<<1|1], r)).first; //该区间的最大后缀 sub[rt] = better (sub[rt<<1], sub[rt<<1|1]); //该区间的最大连续和:max (左前缀,右后缀+左前缀,右后缀) sub[rt] = better (sub[rt], make_pair (suf[rt<<1], pre[rt<<1|1])); //不一定就是最大前缀或最大后缀 } void build(int l, int r, int rt) { if (l == r) { pre[rt] = suf[rt] = l; sub[rt] = make_pair (l, l); return ; } int mid = (l + r) >> 1; build (lson); build (rson); push_up (l, r, rt); } P query_pre(int ql, int qr, int l, int r, int rt) { if (pre[rt] <= qr) return make_pair (l, pre[rt]); int mid = (l + r) >> 1; if (qr <= mid) return query_pre (ql, qr, lson); P p = query_pre (ql, qr, rson); p.first = l; return better (p, make_pair (l, pre[rt<<1])); } P query_suf(int ql, int qr, int l, int r, int rt) { if (suf[rt] >= ql) return make_pair (suf[rt], r); int mid = (l + r) >> 1; if (ql > mid) return query_suf (ql, qr, rson); P p = query_suf (ql, qr, lson); p.second = r; return better (p, make_pair (suf[rt<<1|1], r)); } P query(int ql, int qr, int l, int r, int rt) { if (ql <= l && r <= qr) return sub[rt]; int mid = (l + r) >> 1; if (qr <= mid) return query (ql, qr, lson); if (ql > mid) return query (ql, qr, rson); P p1 = query_suf (ql, qr, lson); //ql <= mid < qr P p2 = query_pre (ql, qr, rson); //和push_up一样 P p3 = better (query (ql, qr, lson), query (ql, qr, rson)); //该区间的最大连续和:max (左前缀,右后缀+左前缀,右后缀) return better (p3, make_pair (p1.first, p2.second)); } }st; int main(void) { int n, q, cas = 0; while (scanf ("%d%d", &n, &q) == 2) { for (int i=1; i<=n; ++i) { scanf ("%lld", &sum[i]); sum[i] += sum[i-1]; } st.build (1, n, 1); printf ("Case %d: ", ++cas); int ql, qr; while (q--) { scanf ("%d%d", &ql, &qr); P ans = st.query (ql, qr, 1, n, 1); printf ("%d %d ", ans.first, ans.second); } } return 0; }