求一个序列的长度在L-U的子序列和的最小值。
才刚学线段树,所以第一次建树是用线段【a,b】表示序列中a到b的元素和,结果TLE了。
后来看了网上题解后才知道要用线段【a, b】表示从0到x(a<=x<=b)的最大和。
用S【i】-max就得到了要求的最小子序列和了。
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#define Max 32800
#define max(a, b) (a>b ? a:b)
#define INF 1000000000
struct node
{
int l,r,sum; //sum用来存储最大前n( l<=n<=r)项和
}tr[4*Max]; //开一个4*Max的数组作为树
int n, L, U,s[Max]; //s[Max]保存前n项和,s[0]=0
int minn;
void buildtree( int a, int b, int x) //建树
{
tr[x].l =a;
tr[x].r =b;
if( a==b)
{
tr[x].sum =s[a];
return ;
}
int mid =(a+b)/2;
buildtree( a, mid, x<<1);
buildtree( mid+1, b, (x<<1)+1);
tr[x].sum = max( tr[x<<1].sum, tr[(x<<1)+1].sum);
}
int search( int a, int b ,int x) //查找最大前n项和
{
if( a==tr[x].l && b==tr[x].r)
return tr[x].sum;
int mid =(tr[x].l+tr[x].r)>>1;
if( b<=mid )
return search( a, b, (x<<1));
else if( a>mid)
return search( a, b,(x<<1)+1);
else
return max( search(a, mid,x<<1), search(mid+1, b, (x<<1)+1));
}
int main()
{
while( scanf("%d", &n)==1&& n)
{
scanf("%d%d", &L, &U);
int i;
s[0]=0;
for( i=1; i<=n; i++)
{
scanf("%d", &s[i]);
s[i] +=s[i-1];
}
buildtree(0, n, 1);
minn =INF;
for( i=L; i<=n; i++)
{
int a =max( 0,i-U);
int tem =s[i] -search( a, i-L, 1);
if( tem <minn)
minn =tem;
}
printf("%d\n", minn);
}
return 0;
}