最大连续长度不超过m的子序列和

来源:互联网 发布:ae cc 2014 for mac 编辑:程序博客网 时间:2024/06/06 03:22

题目大意

给定长度为n的序列,取出其中长度不超过m的连续一段,求最大

题解

ans=max{sum[i]sum[j1]}   (i>=j11<=ji+1<=m)
很明显这是O(N2)的暴力
对于位置i它前面sum[j-1]最小即可,也就是静态查询区间最小(ST表/线段树)
我们优化到O(NlogN)
对于一个前缀和,它的下标小于后面的下标,并且它的权值也小于后面的权值,即i<jsum[i]<sum[j]那么我们舍去i,单调队列维护
我们优化到O(N)

const maxn=200005;var x,sum:array[0..maxn]of longint; w:array[0..4*maxn,1..3]of longint; i,j,k:longint; n,m,ans:longint;function max(a,b:longint):longint;begin if a>b then exit(a) else exit(b);end;function min(a,b:longint):longint;begin if a<b then exit(a) else exit(b);end;procedure build(a,l,r:longint);var mid:longint;begin w[a,1]:=l; w[a,2]:=r; w[a,3]:=0; if l=r then begin w[a,3]:=sum[l]; exit; end; mid:=(l+r)>>1; build(a<<1,l,mid); build(a<<1+1,mid+1,r); w[a,3]:=min(w[a<<1,3],w[a<<1+1,3]);end;function query(a,l,r:longint):longint;var mid:longint;begin if (w[a,1]=l)and(w[a,2]=r) then exit(w[a,3]); mid:=(w[a,1]+w[a,2])>>1; if r<=mid then exit(query(a<<1,l,r)) else if l>mid then exit(query(a<<1+1,l,r)) else exit(min(query(a<<1,l,mid),query(a<<1+1,mid+1,r)));end;begin readln(n,m); for i:=1 to n do  begin   read(x[i]); sum[i]:=sum[i-1]+x[i];  end; build(1,1,n); ans:=0; for i:=n downto 2 do  begin   if i-m>0   then ans:=max(sum[i]-query(1,i-m,i-1),ans)   else ans:=max(sum[i]-query(1,1,i-1),ans);  end; ans:=max(ans,x[1]); writeln(ans);end.
0 0
原创粉丝点击