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