中间有一个| 我写成了|| 查了好几个小时 我日
每次询问一段区间最大和的起始和终点坐标 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;
}