题目链接: http://www.spoj.pl/problems/GSS1/
———————————————————————————————————————
题目关键字: 线段树
———————————————————————————————————————
question: 为何这样做能够降低复杂度。
———————————————————————————————————————
#include <stdio.h>
#include <stdlib.h>
struct tree
{
int left;
int right;
int val;
int per;
int suf;
}tree[500010];
int a[50010],sum[50010];
int n = 0,m = 0;
void init(int cur,int l,int r)
{
tree[cur].left = l;
tree[cur].right = r;
if(l!=r)
{
tree[cur].val = 0;
init(cur*2,l,(l+r)/2);
init(cur*2+1,(l+r)/2+1,r);
}
else
{
tree[cur].val = a[l];
tree[cur].per = a[l];
tree[cur].suf = a[l];
}
}
long long max(long long a,long long b,long long c)
{
if(a>b)
{
if(a>c)
return a;
else return c;
}
else
{
if(b>c)
return b;
else return c;
}
}
void create(int cur,int l,int r) //1查总和,2查前缀,3查后缀
{
int m = (l+r)>>1;
if(l!=r)
{
create(cur*2,l,m);
create(cur*2+1,m+1,r);
tree[cur].val = max(tree[cur*2].val,tree[cur*2+1].val,tree[cur*2].suf+ tree[cur*2+1].per);
tree[cur].per = max(tree[cur*2].per,tree[cur*2+1].per+ sum[m] - sum[l-1],-9223372036854775808);
tree[cur].suf = max(tree[cur*2+1].suf,sum[r]-sum[m]+ tree[cur*2].suf,-9223372036854775808);
}
}
struct tree query(int cur,int l,int r) //返回的是一个值
{
int m = (tree[cur].left + tree[cur].right)/2; //值一定要搞清楚
struct tree ans,le,ri;
if(tree[cur].left == l && tree[cur].right == r)
return tree[cur];
if(r<=m) return query(cur*2,l,r);
else if(l>m) return query(cur*2+1,l,r);
else
{
le = query(cur*2,l,m);
ri = query(cur*2+1,m+1,r);
ans.per = max(le.per,sum[le.right]-sum[le.left-1]+ ri.per,-9223372036854775808);
ans.suf = max(ri.suf,sum[ri.right]-sum[ri.left-1]+ le.suf,-9223372036854775808);
ans.val = max(le.suf+ri.per,le.val,ri.val);
return ans;
}
}
int main()
{
int i = 0;
int l = 0,r = 0;
struct tree ans ;
scanf("%d",&n);
sum[0] = 0;
for(i = 1;i<=n;i++)
{
scanf("%d",&a[i]);
sum[i] = a[i] + sum[i-1];
}
init(1,1,n);
create(1,1,n);
scanf("%d",&m);
for(i = 0;i<m;i++)
{
scanf("%d%d",&l,&r);
ans = query(1,l,r);
printf("%I64d\n",ans.val);
}
return 0;
}