动态最大连续和。
思路:完全参照刘汝佳厚书的思路。
几天前,就从书上得到一个思路,却不知怎么实现,于是乎,几天来一直广搜结题报告,结合人家现成的代码,今天写成了代码,又调了半下午的bug,终于ac了。
构造一课线段树,其中每个节点维护3个信息,最大连续和(x,y),最大前缀和(pre),最大后缀和(suf),虽然都叫做什么什么和,存的却都是位置标记,
1、建树
2、若干次查询
这道题目没有加入树节点的修改,算是数据结构中的基础题了。
思路来自于静态最大连续和的求解,(最大连续和或在[1...m],或在[m+1......n],或在[x...m......y])
代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
#define M 500005
struct Node{
int x, y, pre, suf, subx, suby;
};
int n, m;
long long a[M], sum[M];
Node tree[2*M+10];
void creat(int x, int y, int o)
{
if(x==y)
{
tree[o].x = x;
tree[o].y = x;
tree[o].pre = x;
tree[o].suf = x;
tree[o].subx = x;
tree[o].suby = x;
return;
}
int m = (x+y)/2;
creat(x, m, 2*o);
creat(m+1, y, 2*o+1);
tree[o].x = x;
tree[o].y = y;
tree[o].pre = sum[tree[2*o].pre]-sum[x-1] >= sum[tree[2*o+1].pre]-sum[x-1] ? tree[2*o].pre : tree[2*o+1].pre;
tree[o].suf = sum[y]-sum[tree[2*o].suf-1] >= sum[y]-sum[tree[2*o+1].suf-1] ? tree[2*o].suf : tree[2*o+1].suf;
if(sum[tree[2*o].suby]-sum[tree[2*o].subx-1]>=sum[tree[2*o+1].suby]-sum[tree[2*o+1].subx-1])
{ tree[o].suby = tree[2*o].suby; tree[o].subx = tree[2*o].subx; }
else
{ tree[o].suby = tree[2*o+1].suby; tree[o].subx = tree[2*o+1].subx; }
if(sum[tree[2*o+1].pre]-sum[tree[2*o].suf-1] > sum[tree[o].suby]-sum[tree[o].subx-1])
{ tree[o].subx = tree[2*o].suf; tree[o].suby = tree[2*o+1].pre; }
else if(sum[tree[2*o+1].pre]-sum[tree[2*o].suf-1] == sum[tree[o].suby]-sum[tree[o].subx-1])
{
if(tree[o].subx > tree[2*o].suf||(tree[o].subx == tree[2*o].suf && tree[o].suby > tree[2*o+1].pre))
{ tree[o].subx = tree[2*o].suf; tree[o].suby = tree[2*o+1].pre; }
}
}
void buildtree()
{
creat(1,n,1);
}
void query(int o, int ql, int qr, int &ansx, int &ansy, int &pre, int &suf)
{
int x = tree[o].x, y = tree[o].y;
if(ql<=x&&qr>=y)
{
ansx = tree[o].subx;
ansy = tree[o].suby;
pre = tree[o].pre;
suf = tree[o].suf;
return ;
}
int mid = (x+y)/2;
if(qr<=mid) query(2*o,ql,qr,ansx,ansy,pre,suf);
else if(ql>mid) query(2*o+1,ql,qr,ansx,ansy,pre,suf);
else
{
int x1, x2, y1, y2,p1,p2,s1,s2;
query(2*o,ql,mid,x1,y1,p1,s1);
query(2*o+1,mid+1,qr,x2,y2,p2,s2);
pre = sum[p1]-sum[ql-1] >= sum[p2]-sum[ql-1] ? p1 : p2 ;
suf = sum[qr]-sum[s1-1] >= sum[qr]-sum[s2-1] ? s1 : s2 ;
if(sum[y1]-sum[x1-1] >= sum[y2]-sum[x2-1])
{
ansx = x1;
ansy = y1;
}
else
{
ansx = x2;
ansy = y2;
}
long long L = sum[m]-sum[s1-1];
long long R = sum[p2]-sum[m];
if(L+R > sum[ansy]-sum[ansx-1] || (L+R == sum[ansy]-sum[ansx-1] && ansx > s1) || (L+R == sum[ansy]-sum[ansx-1] && ansx == s1 && ansy > p2))
{
ansx = s1;
ansy = p2;
}
}
}
int main ()
{
int k = 0;
while(~scanf("%d %d",&n, &m))
{
for(int i = 1; i <= n; ++i)
{
scanf("%lld",&a[i]);
sum[i] = sum[i-1]+a[i];
}
buildtree();
int ql, qr, ansx, ansy,pre,suf;
printf("Case %d:\n",++k);//不要把case放错位置哦
while(m--)
{
scanf("%d %d",&ql, &qr);
query(1, ql, qr, ansx, ansy,pre,suf);
printf("%d %d\n", ansx, ansy);
}
}
return 0;
}