hdu 3415 Max Sum of Max-K-sub-sequence 单调队列优化DP

题目链接: https://www.cnblogs.com/Draymonder/p/9536681.html

同上一篇文章,只是 需要记录最大值的开始和结束的位置

#include <iostream>
#include <string.h>
#include <cmath>
using namespace std;
const int N = 1e5 + 10;

int n,k;
int s[N<<1],sum[N<<1];
int Q[N<<1];

int main ()
{
    freopen("in.txt","r",stdin);
    int T; scanf("%d",&T);
    while (T--) {
        memset(Q,0,sizeof(Q));
        memset(sum,0,sizeof(sum));
        scanf("%d %d", &n, &k);
        for(int i=1; i<=n; i++) 
            scanf("%d",&s[i]), s[i+n]=s[i];
        n<<=1;
        for(int i=1;i<=n;i++)
            sum[i] = sum[i-1]+s[i]; //printf("%d ",sum[i]);
        // for(int i=1;i<=n;i++)
        //     printf("%d ", sum[i]);
        // puts("");
        int mx = -N, ans1=n+1,ans2=-1;
        for(int i=1;i<=n;i++) {
            if(i <= k) {
                if(sum[i] > mx) {
                    mx = sum[i];
                    ans1=1,ans2=i;
                }
            }
        }
        //printf("%d %d
",ans1, ans2);
        int st=0,ed=0;
        for(int i=1; i<=n; i++)    {
            //[i-k+1,i] 区间长度为k
            while (st < ed && Q[st] < i-k) 
                st++;
            if(st < ed) {
                int ans = sum[i] - sum[Q[st]];
                if(mx < ans) {
                    mx =ans;
                    ans1 = Q[st]+1;
                    ans2 = i;
                }
            }
            while (st < ed && sum[i] <= sum[Q[ed-1]])
                ed--;
            Q[ed++] = i;
            //cout << i<<" "<<ans1 <<" "<<ans2<<endl;
        }
        printf("%d %d %d
", mx, ans1>n/2?ans1-n/2:ans1, ans2>n/2?ans2-n/2:ans2);

    }
    return 0;
}