HDU 3415/ Max Sum of Max-K-sub-sequence/单调队列?尺取?

文章探讨了两种处理数组子序列和的方法,一是尺取法,通过双指针优化,但遇到了TLE和WA的问题;二是单调队列,用于维护递增序列并寻找最小前缀和,提供了解决此类问题的思路。
摘要由CSDN通过智能技术生成

可以尺取吗?//先看代码上一行

尺取,双指针:我先限定 l = 1;让 r 向后走,走到 r - l + 1 正好为 题目所给的 n 在这个过程中,我们判断我们所需要的答案,之后让 l 后移 1 位,用循环吧a【l】小于等于 0 的给删掉;

删完后在判断这个是否是我们需要的答案,重复此过程,直至遍历完整个数组。

这个的分析感觉一点错都没有,先是TLE,之后又是WA,找不到哪里有问题。

#include<iostream>
using namespace std;
const int N=1e6+5;
int a[N],ans[N];
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int m,n;
		scanf("%d%d",&m,&n);
		
		for(int i=1;i<=m;i++)
		{
			scanf("%d",&a[i]);
			ans[i]=ans[i-1]+a[i];
		}
		for(int i=1;i<n;i++)
			ans[i+m]=ans[m+i-1]+a[i];
		
		int sum=ans[1],ml=1,mr=1;
		
		
		for(int l=1,r=1;l<m||r<n+m-1;)//1 2 3  位置应该是合理即可,顺序都可以
		{
			while(a[l]<=0&&l<r)		l++;//    1
			if(sum<ans[r]-ans[l-1])
			{
				ml=l;mr=r;
				sum=ans[r]-ans[l-1];
			}
			
			while(r-l<n&&r<m+n-1)//    2
			{
				r++;
				if(sum<ans[r]-ans[l-1])
				{
					ml=l;mr=r;
					sum=ans[r]-ans[l-1];
				}
			}
			
			if(l<m)	l++;//    3
		}
		
		printf("%d %d %d\n",sum,ml,mr-mr/(m+1)*m);
	}
	return 0;
}

单调队列//双端队列

 维护一个递增的队列(对于每一个 i ,队列都是不一样的),我们取寻找当前 i 之前最小的前缀和

;可能还是有点蒙,我们需要取找每一个 i 值所对应的那个最小值(当前 子序列的和 是当前 i 与之前的差 及sum【i】-sum【q . front()】),前面比 i 大的在之前已经找过,无需在多考虑。先敲一下,进行理解

在看看HDU1003

#include<iostream>
#include<deque>
using namespace std;
const int N=1e6+5;
int a[N],sum[N];
int main()
{
	ios::sync_with_stdio(0);
	int T;
	cin>>T;
	while(T--)
	{
		int m,n,x;
		cin>>m>>n;a[0]=0;
		for(int i=1;i<=m;i++)
		{
			cin>>a[i];
			sum[i]=sum[i-1]+a[i];
		}
		
		for(int i=1;i<=n;i++)
			sum[i+m]=sum[m+i-1]+a[i];
		
		deque<int>q;
		int ans=-1000000010,ml=1,mr=1;
		for(int i=1;i<=m+n;i++)
		{
			while(q.size()&&sum[i-1]<sum[q.back()])
				q.pop_back();
			while(q.size()&&i-q.front()>n)
				q.pop_front();
			q.push_back(i-1);
			if(ans<sum[i]-sum[q.front()])
			{
				ans=sum[i]-sum[q.front()];
				ml=q.front()+1;
				mr=i;
			}
		}
		cout<<ans<<' '<<ml<<' '<<mr-mr/(m+1)*m<<'\n';
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值