北大ACM3061——Subsequence

题目大概的意思是:给你一个整数数列,从中找出最小连续子序列的和不小于整数S。

数列最小为10,最大为100000,用暴力法估计会超时,我没有试过。

这里,我将用两种方法来求解这一题,一个时间复杂度为nlogn,另一个时间复杂度为n,不过两个提交了,时间都是79MS。没多大的区别。

1.时间复杂度为nlogn的方法:

主要的思路是用一个数组 sum 算出数列的前 i+1 个数的和,(i从0到n),然后每一个数列sum的每一个都加上S,再在数组sum中查找不小于sum[i] + S的位置ans。ans - i 就是不小于S的序列的长度,不断更新ans - i,就可以将解求出。

algorithm  中有一个函数lower_bound 就是求解一段数组中不小于一个数的下标。

下面的是AC的代码:

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

int a[100005], sum[100005];

int min(int x, int y)
{
	return x > y ? y : x;
}
void solve(int n, int s)
{
	int i, j;
	for(i = 0; i < n; i++)                //计算前i+1个数的和
		sum[i + 1] = sum[i] + a[i];
	if(sum[n] < s)                        //全部数之和小于s,直接输出0
		printf("0\n");
	else
	{
		int res = n;
		for(j = 0; sum[j] + s <= sum[n]; j++) //在sum数组中,查找不小于s + sum【j】的位置,不断的更新
		{
			int ans = lower_bound(sum + j, sum + n, sum[j] + s) - sum;  //返回不小于s + sum【j】的位置
			res = min(res, ans - j);                                    //比较res与ans - j谁小。不断更新
		}
		printf("%d\n", res);
	}
}

int main()
{
	int t, n, s;
	scanf("%d", &t);
	while(t--)
	{
		scanf("%d%d", &n, &s);
		memset(sum, 0, sizeof(sum));         //初始化,
		for(int i = 0; i < n; i++)
			scanf("%d", &a[i]);
		solve(n, s);
	}
	return 0;
}

2.时间复杂度为n的方法:

主要的思路就是:设置两个位置的标志,一个s为不小于m的序列的起始位置,一个t为不小于m的序列的末尾位置。一开始s =  t = 0,设置一个序列和sum = 0;开始 sum += a【t++】直到 sum > m,算出序列长度 t - s;然后sum - a【s++】;看sum 是否还大于m,不大于,就继续加上a【t++】,否则则更新序列长度,sum - a【s++】;

不断的这样更新,就可以求出最小的序列长度。

对于文字不是很理解,可以看下面的图示。

下面的是AC的另一段代码:

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

int a[100005];

int min(int x, int y)
{
	return x > y ? y : x;
}

void solve(int n, int m)
{
	int res = n + 1;
	int s, t, sum;
	s = t = sum = 0;
	while(1)
	{
		while(t < n && sum < m)          //累加a数组,直到sum > m
		{
			sum += a[t++];
		}
		if(sum < m)                       //如果总和小于m,则退出
			break;
		res = min(res, t - s);            //算出序列长度
		sum -= a[s++];                    //序列起始位置去掉一个,再进行循环
	}
	if(res > n)
		res = 0;
	printf("%d\n", res);
}

int main()
{
	int t, n, s;
	scanf("%d", &t);
	while(t--)
	{
		scanf("%d%d", &n, &s);
		for(int i = 0; i < n; i++)
			scanf("%d", &a[i]);
		solve(n, s);
	}
	return 0;
}
时间: 2024-10-25 19:30:39

北大ACM3061——Subsequence的相关文章

北大ACM题库习题分类与简介(转载)

在百度文库上找到的,不知是哪位大牛整理的,真的很不错! zz题 目分类 Posted by fishhead at 2007-01-13 12:44:58.0 -------------------------------------------------------------------------------- acm.pku.edu.cn 1. 排序 1423, 1694, 1723, 1727, 1763, 1788, 1828, 1838, 1840, 2201, 2376, 23

LintCode刷题笔记--Longest Increasing Subsequence

动态规划 描述: Given a sequence of integers, find the longest increasing subsequence (LIS). You code should return the length of the LIS. Clarification What's the definition of longest increasing subsequence? The longest increasing subsequence problem is t

北大POJ题库使用指南

原文地址:北大POJ题库使用指南 北大ACM题分类主流算法: 1.搜索 //回溯 2.DP(动态规划)//记忆化搜索 3.贪心 4.图论 //最短路径.最小生成树.网络流 5.数论 //组合数学(排列组合).递推关系.质因数法 6.计算几何 //凸壳.同等安置矩形的并的面积与周长.凸包计算问题 8.模拟 9.数据结构 //并查集.堆.树形结构 10.博弈论 11.CD有正气法题目分类: 1. 排序 1423, 1694, 1723, 1727, 1763, 1788, 1828, 1838, 1

POJ 2533 - Longest Ordered Subsequence(最长上升子序列) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=2533 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1, ai2, ..., aiK)

Longest Common Subsequence

Problem statement: Given two strings, find the longest common subsequence (LCS). Your code should return the length of LCS. Have you met this question in a real interview? Yes Clarification What's the definition of Longest Common Subsequence? https:/

中南OJ1551: Longest Increasing Subsequence Again(分块+离散化线段树)

1551: Longest Increasing Subsequence Again Time Limit: 2 Sec  Memory Limit: 256 MB Submit: 29  Solved: 15 [Submit][Status][Web Board] Description Give you a numeric sequence. If you can demolish arbitrary amount of numbers, what is the length of the

ZOJ3349——Special Subsequence

Special Subsequence Time Limit: 5 Seconds      Memory Limit: 32768 KB There a sequence S with n integers , and A is a special subsequence thatsatisfies |Ai-Ai-1| <= d ( 0 <i<=|A|)) Now your task is to find the longest special subsequence of a cer

POJ 3061 Subsequence

Description 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 o

Common Subsequence

A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = < x1, x2, ..., xm > another sequence Z = < z1, z2, ..., zk > is a subsequence of X if there exists a strictly increasing