【题目大意】:给出一个数组,把其首尾相接起来,然后给定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;
}