注意分清三种情况,并且保证字典序最小
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define ls o<<1
#define rs o<<1|1
#define lson L, mid, ls
#define rson mid+1, R, rs
using namespace std;
const int maxn = 5e5 + 10;
typedef long long ll;
int n, m;
ll s[maxn];
struct Node
{
int vl, vr;//解区间
int suf, pre;//后缀的最左端、前缀的最右端
}tree[maxn<<2];
void pushup(int l, int r, int o)
{
tree[o].pre = (s[tree[ls].pre]-s[l-1] >= s[tree[rs].pre]-s[l-1]) ? tree[ls].pre : tree[rs].pre;
tree[o].suf = (s[r]-s[tree[ls].suf-1] >= s[r]-s[tree[rs].suf-1]) ? tree[ls].suf : tree[rs].suf;
ll v1 = s[tree[ls].vr] - s[tree[ls].vl-1];//起点、终点都在左孩子
ll v2 = s[tree[rs].vr] - s[tree[rs].vl-1];//起点、终点都在右孩子
ll v0 = s[tree[rs].pre] - s[tree[ls].suf-1];//起点、终点一个在左,一个在右
tree[o].vl = v1>=v2 ? tree[ls].vl : tree[rs].vl;
tree[o].vr = v1>=v2 ? tree[ls].vr : tree[rs].vr;
if(v0 == s[tree[o].vr]-s[tree[o].vl-1])//保证字典序最小
{
if(tree[ls].suf < tree[o].vl)
{
tree[o].vl = tree[ls].suf;
tree[o].vr = tree[rs].pre;
}
else if(tree[ls].suf==tree[o].vl && tree[rs].pre<tree[o].vr)
{
tree[o].vr = tree[rs].pre;
}
}
if(v0 > s[tree[o].vr]-s[tree[o].vl-1])
{
tree[o].vl = tree[ls].suf;
tree[o].vr = tree[rs].pre;
}
}
void build(int L, int R, int o)
{
if(L==R)
{
tree[o].pre = tree[o].suf = tree[o].vl = tree[o].vr = L;
return ;
}
int mid = (L+R) >> 1;
build(lson);
build(rson);
pushup(L, R, o);
}
Node query(int l, int r, int L, int R, int o)
{
if(l<=tree[o].vl && tree[o].vr<=r)
{
return tree[o];
}
int mid = (L+R) >> 1;
if(r<=mid)
return query(l, r, lson);
if(l>mid)
return query(l, r, rson);
Node a = query(l, r, lson);
Node b = query(l, r, rson);
Node c;
c.vl = (s[a.vr]-s[a.vl-1] >= s[b.vr]-s[b.vl-1]) ? a.vl : b.vl;
c.vr = (s[a.vr]-s[a.vl-1] >= s[b.vr]-s[b.vl-1]) ? a.vr : b.vr;
c.pre = (s[a.pre]-s[l-1] >= s[b.pre]-s[l-1]) ? a.pre : b.pre;
c.suf = (s[r]-s[a.suf-1] >= s[r]-s[b.suf-1]) ? a.suf : b.suf;
//保证字典序最小
if(s[b.pre]-s[a.suf-1] == s[c.vr]-s[c.vl-1])
{
if(a.suf < c.vl)
{
c.vl = a.suf;
c.vr = b.pre;
}
if(a.suf==c.vl && b.pre<c.vr)
{
c.vr = b.pre;
}
}
if(s[b.pre]-s[a.suf-1] > s[c.vr]-s[c.vl-1])
{
c.vl = a.suf;
c.vr = b.pre;
}
return c;
}
int main()
{
int flag = 1;
while(scanf("%d%d", &n, &m)!=EOF)
{
memset(s, 0, sizeof s);
for(int i = 1; i <= n; i++)
{
ll x;
scanf("%lld", &x);
s[i] = s[i-1] + x;
}
printf("Case %d:\n", flag++);
build(1, n, 1);
while(m--)
{
int a, b;
scanf("%d%d", &a, &b);
Node ans = query(a, b, 1, n, 1);
printf("%d %d\n", ans.vl, ans.vr);
}
}
}