hdu 3415 Max Sum of Max-K-sub-sequence

题意:给定一个含有n个数的序列,从中找出连续长度不超过k的非空子序列,使其和最大。(n<=10^5,k<=10^5)

解法:考虑最朴素的做法,用maxn[i]表示以i为结尾,长度不超过k的非空子序列的最大和,那么有maxn[i]=sum[i]-max{sum[i-1]...sum[i-k]},直接做的话时间复杂度O(n*k),看到表达式中后一部分,可以采用单调队列解决,维护一个sum[i]单调递增的单调队列,那么每次求解maxn[i]就可以直接取队列头,复杂度降到O(1),由于长度不大于k,所以每次插入之后还要删掉不满足条件的队头元素。。。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define N 200010
 5 using namespace std;
 6 int s[N],sum[N];
 7 int id[N];
 8 int main(){
 9     int n,k,t;
10     scanf("%d",&t);
11     while(t--){
12         scanf("%d%d",&n,&k);
13         sum[0]=0;
14         for(int i=1;i<=n;i++){
15             scanf("%d",&s[i]);
16             s[i+n]=s[i];
17         }
18         for(int i=1;i<=n*2;i++)
19             sum[i]=sum[i-1]+s[i];
20         int l,r;
21         int ans=-(1<<30);
22         l=1,r=0;
23         int st,ed;
24         for(int i=1;i<=n*2;i++){
25             while(l<=r&&sum[i-1]<sum[id[r]])--r;
26             id[++r]=i-1;
27             while(l<=r&&i-id[l]>k)++l;
28             if(ans<sum[i]-sum[id[l]]){
29                 ans=sum[i]-sum[id[l]];
30                 st=id[l]+1;
31                 ed=i;
32             }
33         }
34         printf("%d %d %d\n",ans,st>n?(st%n):st,ed>n?(ed%n):ed);
35     }
36     return 0;
37 }

 

posted @ 2012-12-05 23:29  silver__bullet  阅读(161)  评论(0编辑  收藏  举报