Subsequence POJ - 3061(尺取法||二分)

A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, and a positive integer S (S < 100 000 000) are given. Write a program to find the minimal length of the subsequence of consecutive elements of the sequence, the sum of which is greater than or equal to S.
Input
The first line is the number of test cases. For each test case the program has to read the numbers N and S, separated by an interval, from the first line. The numbers of the sequence are given in the second line of the test case, separated by intervals. The input will finish with the end of file.
Output
For each the case the program has to print the result on separate line of the output file.if no answer, print 0.
Sample Input
2
10 15
5 1 3 5 10 7 4 9 2 8
5 11
1 2 3 4 5
Sample Output
2
3
思路:因为在刷尺取法专题,所以就往尺取上靠了。这是个比较基础的尺取了吧。这个题目二分也可以,满足单调性是可以进行二分的。
代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;

const int maxx=1e5+100;
int a[maxx];
int n,m;

int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		int l=1,r=1;
		int ans=0;
		int sum=1e9+1;
		while(r<=n)
		{
			while(ans<m&&r<=n) ans+=a[r],r++;
			while(ans>=m) ans-=a[l],l++;
			if(r<=n)sum=min(sum,r-l+1);
		}
		printf("%d\n",sum==1e9+1?0:sum);
	}
	return 0;
}

二分代码:

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int n,s;
int a[100010];
int ans;
int ko(int m)
{
	if(s==0) return 1;
	int temp=0;
	for(int i=1;i<=n-(m-1);i++)
	{
		temp=a[i+(m-1)]-a[i-1];
		if(s<=temp) return 1;
	}
	return 0;
}
void sde()
{
	ans=0;
	int l=1,r=n;
	int m=(l+r)/2;
	while(l<r)
	{
		if(ko(m)) r=m;
		else l=m+1;
		m=(l+r)/2;
	}
	ans=m;
}
void input()
{
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		a[i]=a[i-1]+a[i];
	}
}
int main()
{
	int k;
	cin>>k; 
	while(k--)
	{
		cin>>n>>s;
		input();
		sde();
		if(ans!=n)
		cout<<ans<<endl;
		else if(a[n]<s)
		{
			cout<<0<<endl;
		}
		else cout<<n<<endl;
	}
	return 0;
}

努力加油a啊,(o)/~

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
题目描述 给定K个整数组成的序列{ N1, N2, ..., NK },“连续子列”被定义为{ Ni, Ni+1, ..., Nj },其中 1≤i≤j≤K。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{-2, 11, -4, 13, -5, -2},其最大子列和为20,对应子列为{ 11, -4, 13 }。 现在你应该给出一个算法,计算给定整数序列的最大子列和。 输入格式 输入第1行给出正整数K(K≤10000),第2行给出K个整数,其间以空格分隔。 输出格式 在一行中输出最大子列和。如果序列中所有整数皆为负数,则输出。 输入样例 6 -2 11 -4 13 -5 -2 输出样例 20 算法1 (暴力枚举) $O(n^2)$ 暴力枚举所有的子序列,计算它们的和,最后找到最大的和即可。 时间复杂度 枚举所有子序列,时间复杂度为$O(n^2)$。 C++ 代码 算法2 (分治) $O(nlogn)$ 将序列分成左右两部分,最大子序列和可能在左边、右边或者跨越中间。如果最大子序列和在左边或者右边,那么可以递归求解;如果最大子序列和跨越中间,那么可以分别求出左边的最大后缀和和右边的最大前缀和,然后将它们相加即可。 时间复杂度 每次递归都会将序列分成两部分,时间复杂度为$O(logn)$,而每次计算跨越中间的最大子序列和的时间复杂度为$O(n)$,所以总的时间复杂度为$O(nlogn)$。 C++ 代码 算法3 (动态规划) $O(n)$ 用dp[i]表示以i结尾的最大子序列和,那么dp[i]的值可以由dp[i-1]和a[i]计算得到。如果dp[i-1]是负数,那么dp[i]就是a[i];否则dp[i]就是dp[i-1]+a[i]。最后找到dp数组中的最大值即可。 时间复杂度 只需要遍历一遍数组,时间复杂度为$O(n)$。 C++ 代码

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

starlet_kiss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值