题意
给你一个序列,要找出一个子序列使得子序列的长度小于等于k,让子序列值最大,输出最大值并且输出子序列的左右位置
思路
利用前缀和的思想,sum[i]-sum[j],i-j<=k就是我们要求的子序列。
我们用单调队列维护这个前缀,队列里放的是[i-k,i-1],并且因为是单调队列所以队列的首部是最小的,我们只需要求sum[i]-sum[dq.front()]然后取个max就可以了。
#include <iostream>
#include <deque>
using namespace std;
deque<int> dq;
int num[222222];
int sum[222222];
int main()
{
int T;cin>>T;
while(T--)
{
int n,k;
cin>>n>>k;
sum[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&num[i]);
sum[i]=sum[i-1]+num[i];
}
int ans=-0x3f3f3f3f;
for(int i=n+1;i<=n+k;i++)
sum[i]=sum[i-1]+num[i-n];
dq.clear();
int l,r;
for(int i=1;i<=n+k;i++)
{
while(!dq.empty()&&sum[i-1]<sum[dq.back()])
dq.pop_back();
while(!dq.empty()&&i-dq.front()>k)
dq.pop_front();
dq.push_back(i-1);
if(sum[i]-sum[dq.front()]>ans)
{
ans=sum[i]-sum[dq.front()];
l=dq.front()+1;
r=i;
}
}
if(l>n) l-=n;
if(r>n) r-=n;
printf("%d %d %d\n",ans,l,r);
}
return 0;
}