[HDU 3415] Max Sum of Max-K-sub-sequence · 单调队列

大概就是求一个环形序列里长度不超过k的最大子段和。

因为是环形,所以我们可以把序列复制一遍。

对于每个i,我们要求的就是一个j,使得i-j+1<=k且j~i这段和是最大的,然后和答案比较。

那怎么求呢?把前缀和处理出来,i~j的序列和就是s[i]-s[j-1],i是每次枚举的,已经确定,所以我们就是需要求最小的s[j-1]。

我们可以用递增的单调队列来维护前缀和,队列中存的是下标。

另外就是一些细节处理。

#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;

const int N=100005*2;	
int n,T,k,data[N],q[N],l,r,s[N],ans,beg,en;

int get(){
	char x=getchar();int p=0,t=1;
	while (x<'0' || x>'9') {
		if (x=='-') t=-1;
		x=getchar();
	}
	while (x>='0' && x<='9') p=p*10+x-'0',x=getchar();
	return p*t;
}

int main(){
	T=get();
	while (T--){
		n=get();k=get();
		for (int i=1;i<=n;i++) {
			data[i]=get();
			s[i]=s[i-1]+data[i];
		}
		for (int i=1;i<=k;i++)
			s[i+n]=data[i]+s[i+n-1];
		beg=en=1;ans=data[1];
		
		l=r=1;q[1]=0;
		for (int i=1;i<=n+k;i++){
			for (;l<=r && i-q[l]>k;l++);	//剔除不合法的值 
			if (l<=r){
				if (s[i]-s[q[l]]>ans) ans=s[i]-s[q[l]],beg=q[l]+1,en=i;
				if (s[i]-s[q[l]]==ans){
					if (q[l]+1<beg) beg=q[l]+1,en=i;
					if (q[l]+1==beg) en=min(en,i);
				}
			}
			for (;s[q[r]]>=s[i] && r>=l;r--);
			q[++r]=i;
		}
		if (beg>n) beg-=n;
		if (en>n) en-=n;
		printf("%d %d %d\n",ans,beg,en);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值