中间有一个| 我写成了|| 查了好几个小时 我日
每次询问一段区间最大和的起始和终点坐标 x,y
x y 尽量小
对于某个节点 最大和要么是左子树的最大和 要么是右子树的最大值 要么是左右各有
最后一中情况要保存最大前缀和最大后缀 取左子树的最大后缀和右子树的最大前缀
最大前缀也要更新
一个节点的最大前缀等于1.左子树的最大前缀2.坐子树所有数的和加上右子树的和 2者取大
最大后缀相同
和相同x尽量小x一样y尽量小 多加判断
#include <iostream> #include <stack> #include <queue> #include <cstdio> #include <cstdlib> #include <cmath> #include <set> #include <vector> #include <cstring> #include <algorithm> #define LL long long using namespace std; const int maxn = 500010; struct node { int l; int r; int sl; int sr; int ll; int rr; LL pre; LL post; LL sum; }a[maxn<<2]; LL b[maxn]; void build(int l, int r, int rt) { a[rt].l = l; a[rt].r = r; if(l == r) { a[rt].ll = a[rt].rr = l; a[rt].sl = a[rt].sr = l; a[rt].sum = a[rt].pre = a[rt].post = b[l] - b[l-1]; return; } int m = (l + r) >> 1; build(l, m, rt<<1); build(m+1, r, rt<<1|1); a[rt].pre = a[rt<<1].pre; a[rt].ll = a[rt<<1].ll; if(a[rt].pre < b[m] - b[l-1] + a[rt<<1|1].pre) { a[rt].pre = b[m] - b[l-1] + a[rt<<1|1].pre; a[rt].ll = a[rt<<1|1].ll; } a[rt].post = a[rt<<1|1].post; a[rt].rr = a[rt<<1|1].rr; if(a[rt].post <= b[r] - b[m] + a[rt<<1].post) { a[rt].post = b[r] - b[m] + a[rt<<1].post; a[rt].rr = a[rt<<1].rr; } a[rt].sum = a[rt<<1].sum; a[rt].sl = a[rt<<1].sl; a[rt].sr = a[rt<<1].sr; if(a[rt].sum < a[rt<<1|1].sum) { a[rt].sum = a[rt<<1|1].sum; a[rt].sl = a[rt<<1|1].sl; a[rt].sr = a[rt<<1|1].sr; } if(a[rt].sum < a[rt<<1].post + a[rt<<1|1].pre) { a[rt].sum = a[rt<<1].post + a[rt<<1|1].pre; a[rt].sl = a[rt<<1].rr; a[rt].sr = a[rt<<1|1].ll; } else if(a[rt].sum == a[rt<<1].post + a[rt<<1|1].pre) { if(a[rt].sl > a[rt<<1].rr || (a[rt].sl == a[rt<<1].rr && a[rt].sr > a[rt<<1|1].ll)) { a[rt].sl = a[rt<<1].rr; a[rt].sr = a[rt<<1|1].ll; } } } node query(int l, int r, int rt) { if(l == a[rt].l && r == a[rt].r) return a[rt]; int m = (a[rt].l + a[rt].r) >> 1; if(l > m) return query(l, r, rt<<1|1); else if(r <= m) return query(l, r, rt<<1); else { node left = query(l, m, rt<<1); node right = query(m+1, r, rt<<1|1); node u = left; if(u.sum < right.sum) u = right; if(u.sum < left.post + right.pre) { u.sum = left.post + right.pre; u.sl = left.rr; u.sr = right.ll; } else if(u.sum == left.post + right.pre) { if(u.sl > left.rr || (u.sl == left.rr && u.sr > right.ll)) { u.sl = left.rr; u.sr = right.ll; } } u.ll = left.ll; u.pre = left.pre; if(u.pre < b[m] - b[l-1] + right.pre) { u.pre = b[m] - b[l-1] + right.pre; u.ll = right.ll; } u.rr = right.rr; u.post = right.post; if(u.post <= b[r] - b[m] + left.post) { u.post = b[r] - b[m] + left.post; u.rr = left.rr; } return u; } } int main() { int cas = 1; int n, m; while(scanf("%d %d", &n, &m) != EOF) { b[0] = 0; for(int i = 1; i <= n; i++) { scanf("%lld", &b[i]); b[i] += b[i-1]; } build(1, n, 1); printf("Case %d:\n", cas++); while(m--) { int x, y; scanf("%d %d", &x, &y); node ret = query(x, y, 1); printf("%d %d\n",ret.sl,ret.sr); } } return 0; }