构造线段树每个节点维护三个值
max_pre 满足当前线段最大前缀和的右端点编号
max_suf 满足当前线段最大后缀和的左端点编号
max_sub 用pair维护满足当前线段最大连续和的两个端点编号
维护max_sub
有三种情况
左右端点都在 左子节点 max_sub等于左子节点的max_sub
左右端点都在 右子节点 max_sub等于右子节点的max_sub
左端点在 左子节点 右端点在 右子节点 左子节点后缀和+右子节点前缀和
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
using namespace std;
typedef long long LL;
const int maxn=500000+10;
typedef pair<int,int> interval;
LL s[maxn];
int ql,qr;
LL sum(int l,int r)
{
return s[r]-s[l-1];
}
LL sum(interval a)
{
return s[a.second]-s[a.first-1];
}
interval better(interval a,interval b)
{
LL tempa=sum(a),tempb=sum(b);
if(tempa!=tempb) return tempa>tempb?a:b;
return a<b?a:b;
}
struct tree
{
interval max_sub[maxn<<2];
int max_pre[maxn<<2];
int max_suf[maxn<<2];
void build(int node,int l,int r)
{
if(l==r)
{
max_pre[node]=max_suf[node]=l;
max_sub[node]=make_pair(l,l);
return ;
}
int mid=l+(r-l)/2,lc=(node<<1),rc=(node<<1|1);
build(lc,l,mid);
build(rc,mid+1,r);
LL v1=sum(l,max_pre[lc]);
LL v2=sum(l,max_pre[rc]);
if(v1==v2) max_pre[node]=min(max_pre[lc],max_pre[rc]);
else max_pre[node]=v1>v2?max_pre[lc]:max_pre[rc];
v1=sum(max_suf[lc],r);
v2=sum(max_suf[rc],r);
if(v1==v2) max_suf[node]=min(max_suf[lc],max_suf[rc]);
else max_suf[node]=v1>v2?max_suf[lc]:max_suf[rc];
max_sub[node]=better(max_sub[lc],max_sub[rc]);
max_sub[node]=better(max_sub[node],make_pair(max_suf[lc],max_pre[rc]));
}
interval pre_query(int node,int l,int r)
{
if(max_pre[node]<=qr) return make_pair(l,max_pre[node]);
int m=l+(r-l)/2;
int lc=(node<<1),rc=(node<<1|1);
if(qr<=m)
{
return pre_query(lc,l,m);
}
interval i = pre_query(rc,m+1,r);
i.first=l;
return better(i,make_pair(l,max_pre[lc]));
}
interval suf_query(int node,int l,int r)
{
if(max_suf[node]>=ql) return make_pair(max_suf[node],r);
int m=l+(r-l)/2;
int lc=(node<<1),rc=(node<<1|1);
if(ql>m)
{
return suf_query(rc,m+1,r);
}
interval i=suf_query(lc,l,m);
i.second=r;
return better(i,make_pair(max_suf[rc],r));
}
interval query(int node,int l,int r)
{
if(ql<=l&&qr>=r) return max_sub[node];
int m=l+(r-l)/2;
if(ql>m)
{
return query(node<<1|1,m+1,r);
}
if(qr<=m) return query(node<<1,l,m);
int lc=(node<<1),rc=(node<<1|1);
interval i1=suf_query(lc,l,m);
interval i2=pre_query(rc,m+1,r);
interval i3=better(query(lc,l,m),query(rc,m+1,r));
return better(i3,make_pair(i1.first,i2.second));
}
};
tree T;
int main()
{
int n,m,a,kase=0;
interval ans;
while(scanf("%d%d",&n,&m)!=EOF)
{
printf("Case %d:\n", ++kase);
s[0]=0;
for(int i = 0; i < n; ++i)
{
scanf("%d",&a);
s[i+1]=s[i]+a;
}
T.build(1,1,n);
while(m--)
{
scanf("%d%d",&ql,&qr);
ans=T.query(1,1,n);
printf("%d %d\n",ans.first,ans.second);
}
}
return 0;
}