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 }