【单调队列】hdu 3415 Max Sum of Max-K-sub-sequence

38 篇文章 0 订阅
12 篇文章 0 订阅

http://acm.hdu.edu.cn/showproblem.php?pid=3415

题意:求k长度的最大子串和,单调队列

1)STL

原文参考:http://www.cppblog.com/baby-fly/archive/2010/08/04/122213.aspx?Pending=true

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int a[100005],sum[100005];
int main()
{
	int T,N,K,max,i,j,x,y;
	
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&N,&K);
		deque<int>q1;
		sum[0]=0;
		for(i=1;i<=N;i++)
		{
			scanf("%d",&a[i]);
			sum[i]=sum[i-1]+a[i];
		}
		for(i=N+1;i<N+K;i++)
			sum[i]=sum[i-1]+a[i-N];
		max=-100005;//max=sum[j]-sum[i]
		for(j=1;j<N+K;j++)
		{
			while(!q1.empty()&&sum[j-1]<sum[q1.back()])//找出在1~j之间最小的sum[i]
				q1.pop_back();
			while(!q1.empty()&&q1.front()<j-K)//删除超过K区间的先前元素
				q1.pop_front();
			q1.push_back(j-1);
			if(sum[j]-sum[q1.front()]>max)
			{
				max=sum[j]-sum[q1.front()];
				x=q1.front()+1;
				y=j;
			}
		}
		if(y>N) y=y-N;
		printf("%d %d %d\n",max,x,y);
	}
	return 0;
}


 

2)

#include <iostream>
#include <cstdio>
using namespace std;

const int NM=200005;
int sum[NM],a[NM],que[NM];

int main()
{
	int T,tail,head,i,n,k,mmax,x,y;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&k);
		sum[0]=0;
		for(i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			sum[i]=sum[i-1]+a[i];
		}
		for(i=n+1;i<=n+k;i++)
			sum[i]=sum[i-1]+a[i-n];
		
		tail=0;head=1;	
		mmax=-NM;
		for(i=1;i<=n+k;i++)
		{
			while(tail>=head&&sum[i-1]<sum[que[tail]])  //
				tail--;
			while(tail>=head&&que[head]<i-k)  /**/
				head++;
			tail++;
			que[tail]=i-1;  //
			
			if(sum[i]-sum[que[head]]>mmax)  //
			{
				mmax=sum[i]-sum[que[head]];
				x=que[head]+1;
				y=i;
			}
		}
		if(y>n) y-=n;
		printf("%d %d %d\n",mmax,x,y);
	}
	return 0;
}


 

虽然知道会超时,但另一种思想嘛~~

#include<iostream>

#include<cstdio>
#include<queue>
using namespace std;
int a[100005];
int main()
{
int T,N,K,sum,max,i,j,k,x,y;

scanf("%d",&T);
while(T--)
{
scanf("%d%d",&N,&K);
for(i=1;i<=N;i++)
scanf("%d",&a[i]);
max=-100005;
for(i=1;i<=N;i++)
{
sum=0;
for(j=i;j<i+K;j++)
{
if(j>N) k=j-N;
else k=j;
sum+=a[k];
if(max<sum)
{max=sum;x=i,y=k;}
}
}
printf("%d %d %d\n",max,x,y);
}
return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值