题意:
给定一个长度为n的序列fi,然后做m次询问,每次询问[l,r]输出这段区间内和最大的子区间。如果存在多个和最大,那取x较小的,如果还是相同,取y较小的。
题解:
被玩了,一天都在调试中。我用的是code blocks,long long没法用,输出的结果都不对,找了半天才发现。之后又出现将o,p,q定义为全局变量,递归的时候相互影响。
这道题是用线段树解得,只要看到区间询问基本上都想到的是线段树。。定义结构体,元素l和r表示最大和区间,sum表示区间的和,w表示最大和,pre表示这段区间的前缀最大和(即对于区间[L,R],那前缀就是[L,K](L<=K<=R)),suf是后缀,pr是前缀最大和的区间[L,K]中的K,su是后缀最大和区间[K,R]中的K。
区间分治,在递归的时候,最大和区间要么在左区间,要么在右区间,要么就是两个区间各一部分。若o是要求得区间,p,q分别是o的左右区间,那么o.w=max(p.w,q.w,p.suf+q.pre);而前缀最大和和后缀最大和也有类似的关系,o.pre=max(p.pre,p.sum+q.pre);。
注意:由于x和y要竟可能小,所以要注意比较的顺序。
代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <stack>
using namespace std;
#define LL long long
const int maxn=5e5+10;
struct node{
LL pre,suf,w,sum;
int l,r,pr,su;
}e[maxn*4];
LL f[maxn];
void build(int a,int b,int c)
{
if(a==b)
{
e[c].sum=e[c].w=e[c].pre=e[c].suf=f[a];
e[c].l=e[c].r=e[c].pr=e[c].su=a;
return ;
}
int mid=(a+b)/2;
build(a,mid,2*c);
build(mid+1,b,2*c+1);
e[c].sum=e[2*c].sum+e[2*c+1].sum;
LL aa=e[2*c].w,bb=e[2*c+1].w,cc=e[2*c].suf+e[2*c+1].pre;
if(aa>=bb&&aa>=cc){e[c].w=aa;e[c].l=e[2*c].l;e[c].r=e[2*c].r;}
else if(cc>=bb){e[c].w=cc;e[c].l=e[2*c].su;e[c].r=e[2*c+1].pr;}
else {e[c].w=bb;e[c].l=e[2*c+1].l;e[c].r=e[2*c+1].r;}
if(e[2*c].pre>=e[2*c].sum+e[2*c+1].pre)
{
e[c].pre=e[2*c].pre;
e[c].pr=e[2*c].pr;
if(e[c].pr<0)printf("%d\n",e[c].pr);
}
else
{
e[c].pre=e[2*c].sum+e[2*c+1].pre;
e[c].pr=e[2*c+1].pr;
if(e[c].pr<0)printf("%d\n",e[c].pr);
}
if(e[2*c+1].suf>e[2*c].suf+e[2*c+1].sum)
{
e[c].suf=e[2*c+1].suf;
e[c].su=e[2*c+1].su;
}
else
{
e[c].suf=e[2*c+1].sum+e[2*c].suf;
e[c].su=e[2*c].su;
}
}
node query(int c,int l,int r,int L,int R)
{
//printf("%d\n",c);
if(L==l&&R==r)return e[c];
int mid=L+(R-L)/2;
if(r<=mid)return query(2*c,l,r,L,mid);
else if(l>mid)return query(2*c+1,l,r,mid+1,R);
else
{
node p,q,o;
p=query(2*c,l,mid,L,mid);
q=query(2*c+1,mid+1,r,mid+1,R);
o.sum=p.sum+q.sum;
if(p.w>=q.w&&p.w>=p.suf+q.pre){o.w=p.w;o.l=p.l;o.r=p.r;}
else if(p.suf+q.pre>=q.w){o.w=p.suf+q.pre;o.l=p.su;o.r=q.pr;}
else {o.w=q.w;o.l=q.l;o.r=q.r;}
if(p.pre>=p.sum+q.pre)
{
o.pre=p.pre;
o.pr=p.pr;
}
else
{
o.pre=p.sum+q.pre;
o.pr=q.pr;
}
if(q.suf>p.suf+q.sum)
{
o.suf=q.suf;
o.su=q.su;
}
else
{
o.suf=q.sum+p.suf;
o.su=p.su;
}
return o;
}
}
int main()
{
//freopen("D:\\in.txt","r",stdin);
//freopen("C:\\Documents and Settings\\Administrator\\桌面\\false.txt","w",stdout);
int n,m,tt=0;;
while(scanf("%d%d",&n,&m)!=EOF)
{
int i,j,k,x,y,l,r;
for(i=1;i<=n;i++)
scanf("%lld",&f[i]);
build(1,n,1);
node ans;
printf("Case %d:\n",++tt);
for(i=0;i<m;i++)
{
scanf("%d%d",&l,&r);
ans=query(1,l,r,1,n);
//printf("%d %d\n",l,r);
printf("%d %d\n",ans.l,ans.r);
}
}
return 0;
}
/*
10 10
4 -5 -4 -1 4 -1 -3 1 -1 4
5 9
5 8
*/