hdoj 3415 Max Sum of Max-K-sub-sequence(单调队列+dp)

【题目大意】:给出一个数组,把其首尾相接起来,然后给定k值,在这个数组(循环的)里找出最大子序列值(子列长度不超过k)


【解题思路】:我们很容易得到方程:ans[i]=sum[1,i]-min(sum[1,i-k]) ans[i]表示以i结尾的最大值。

   这样的复杂是O(n*k),是不符合题目给的要求的。

                   这里注意我们要把数组破环,即复制一遍。

   因此,我们可以想到用单调队列维护一个min,来达到优化的目的,使得复杂度降为O(n)                   

【代码】:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <cctype>
#include <map>
#include <iomanip>
                   
using namespace std;
                   
#define eps 1e-8
#define pi acos(-1.0)
#define inf 1<<30
#define linf 1LL<<60
#define pb push_back
#define lc(x) (x << 1)
#define rc(x) (x << 1 | 1)
#define lowbit(x) (x & (-x))
#define ll long long

int que[200100],sum[200100];
int le,ri,n,k,p,q,maxx;
int main(){
    int T;
    cin >> T;
    while (T--){
        scanf("%d%d",&n,&k);
        for (int i=1; i<=n; i++){
            scanf("%d",&sum[i]);
            sum[i]+=sum[i-1];
        }   
        for (int i=n+1; i<=n+k; i++) sum[i]=sum[n]+sum[i-n];
        le=0;
        ri=-1;
        maxx=-inf;   
        for (int i=1; i<=n+k; i++){
            while (le<=ri && sum[que[ri]-1]>sum[i-1]) ri--;
            ri++;
            que[ri]=i;
            while (i-que[le]>=k) le++;
            if (sum[i]-sum[que[le]-1]>maxx){
                maxx=sum[i]-sum[que[le]-1];
                p=que[le];
                q=i;
            }
        }
        if (q>n) q=q-n;
        printf("%d %d %d\n",maxx,p,q);
    }
    return 0;
}


你可能感兴趣的:(hdoj 3415 Max Sum of Max-K-sub-sequence(单调队列+dp))