本来是在做伸展树的,发现了一道需要求区间最大连续和的题,然后想起了原来做的这题好像还没过...当时又是后缀,又是前缀,又是最大子区间和,直接调成傻逼了= =...这次回头做了做,感觉思路还是挺清晰的,就是第一次写搓了把区间和也记录了,实际上只记录个下标就够了,区间和预处理一下就行了。主要思路就是用线段树构造并查询四个值,最大子区间的左右端点l_id,r_id,区间最大后缀的起点s_id,区间最大前缀的终点p_id,构造完了直接在线查询就行了...
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#define lson id<<1,l,m
#define rson id<<1|1,m+1,r
using namespace std;
const int maxn=500000+500;
typedef long long ll;
ll sum[maxn];
int l_id[maxn<<2],r_id[maxn<<2],p_id[maxn<<2],s_id[maxn<<2];
int n,m,p,q;
int tt;
struct node
{
int l,r,s,p;
node(){}
node(int x1,int x2,int x3,int x4)
{
l=x1;
r=x2;
s=x3;
p=x4;
}
};
struct segmenttree
{
void pushup(int id,int l,int r)
{
int m=(l+r)>>1;
if (sum[r_id[id<<1]]-sum[l_id[id<<1]-1]<sum[r_id[id<<1|1]]-sum[l_id[id<<1|1]-1])
{
l_id[id]=l_id[id<<1|1];
r_id[id]=r_id[id<<1|1];
}
else
{
l_id[id]=l_id[id<<1];
r_id[id]=r_id[id<<1];
}
if (sum[r_id[id]]-sum[l_id[id]-1]<sum[p_id[id<<1|1]]-sum[s_id[id<<1]-1] ||
(sum[r_id[id]]-sum[l_id[id]-1]==sum[p_id[id<<1|1]]-sum[s_id[id<<1]-1] && l_id[id]>s_id[id<<1])||
(sum[r_id[id]]-sum[l_id[id]-1]==sum[p_id[id<<1|1]]-sum[s_id[id<<1]-1] && l_id[id]==s_id[id<<1] && r_id[id]>p_id[id<<1|1]))
{
l_id[id]=s_id[id<<1];
r_id[id]=p_id[id<<1|1];
}
if (sum[r]-sum[s_id[id<<1|1]-1]>sum[r]-sum[s_id[id<<1]-1])
{
s_id[id]=s_id[id<<1|1];
}
else s_id[id]=s_id[id<<1];
if (sum[p_id[id<<1|1]]-sum[l-1]>sum[p_id[id<<1]]-sum[l-1])
{
p_id[id]=p_id[id<<1|1];
}
else p_id[id]=p_id[id<<1];
}
void build(int id,int l,int r)
{
if (l==r)
{
l_id[id]=r_id[id]=s_id[id]=p_id[id]=l;
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(id,l,r);
}
node query(int L,int R,int id,int l,int r)
{
if (L==l && r== R)
{
return node(l_id[id],r_id[id],s_id[id],p_id[id]);
}
int m=(l+r>>1);
if (R<=m)
{
return query(L,R,lson);
}
else
if (L>m)
{
return query(L,R,rson);
}
else
{
node p1=query(L,m,lson);
node p2=query(m+1,R,rson);
node res;
if (sum[p1.r]-sum[p1.l-1]<sum[p2.r]-sum[p2.l-1])
{
res.l=p2.l;
res.r=p2.r;
}
else
{
res.l=p1.l;
res.r=p1.r;
}
if (sum[p2.p]-sum[p1.s-1]>sum[res.r]-sum[res.l-1] ||
(sum[p2.p]-sum[p1.s-1]==sum[res.r]-sum[res.l-1] && res.l>p1.s) ||
(sum[p2.p]-sum[p1.s-1]==sum[res.r]-sum[res.l-1] && res.l==p1.s && res.r>p2.p))
{
res.l=p1.s;
res.r=p2.p;
}
if (sum[r]-sum[p2.s-1]>sum[r]-sum[p1.s-1])
res.s=p2.s;
else res.s=p1.s;
if (sum[p2.p]-sum[l-1]>sum[p1.p]-sum[l-1])
res.p=p2.p;
else res.p=p1.p;
return res;
}
}
void init()
{
memset(l_id,0,sizeof l_id);
memset(r_id,0,sizeof r_id);
memset(s_id,0,sizeof s_id);
memset(p_id,0,sizeof p_id);
}
}sgt;
int main()
{
// freopen("in.txt","r",stdin);
int tt=0;
while(~scanf("%d%d",&n,&m))
{
tt++;
sgt.init();
for (int i=1; i<=n; i++)
{
scanf("%lld",&sum[i]);
}
for (int i=2; i<=n; i++)
sum[i]+=sum[i-1];
sgt.build(1,1,n);
node ans;
int x,y;
printf("Case %d:\n",tt);
for (int i=1; i<=m; i++)
{
scanf("%d%d",&x,&y);
ans=sgt.query(x,y,1,1,n);
printf("%d %d\n",ans.l,ans.r);
}
}
}