fzu 2216

 Problem 2216 The Longest Straight

Accept: 497    Submit: 1546
Time Limit: 1000 mSec    Memory Limit : 32768 KB

 Problem Description

ZB is playing a card game where the goal is to make straights. Each card in the deck has a number between 1 and M(including 1 and M). A straight is a sequence of cards with consecutive values. Values do not wrap around, so 1 does not come after M. In addition to regular cards, the deck also contains jokers. Each joker can be used as any valid number (between 1 and M, including 1 and M).

You will be given N integers card[1] .. card[n] referring to the cards in your hand. Jokers are represented by zeros, and other cards are represented by their values. ZB wants to know the number of cards in the longest straight that can be formed using one or more cards from his hand.

 Input

The first line contains an integer T, meaning the number of the cases.

For each test case:

The first line there are two integers N and M in the first line (1 <= N, M <= 100000), and the second line contains N integers card[i] (0 <= card[i] <= M).

 Output

For each test case, output a single integer in a line -- the longest straight ZB can get.

 Sample Input

2
7 11
0 6 5 3 0 10 11
8 1000
100 100 100 101 100 99 97 103

 Sample Output

5
3

 Source

第六届福建省大学生程序设计竞赛-重现赛(感谢承办方华侨大学)

题意 :  给你n 张牌上边写着几个数, 如果这张上边写的数 为 0  的话,就表示这张牌可以转化成其他任意小于等于m 的牌,因此需要你来求出 最长的连续子序列  子序列!  

思路:  我们先定义一个card 数组表示  1 (这张牌出现过) 0  (这张牌没有出现)  

现在我们就不应该再研究 原本的序列  而是考虑一下 你所拥有的卡片的数字组成的 序列。  就比如样例1  我们就因该研究  

3  5  6  10  11  和0  之间的关系。  那么我们可以转化一下  设一个sum 数组(当然是递增的,所以我们就可以 用二分)表示  从第数字1到数字i  其中 缺少的 个数字的个数,也就是 我们需要的0 的个数 (因为0 可以去变成每一个数字 ) 然后我们就可以枚举左端点  然后二分去找到右端点,,二分的  要找的位置  就是我们当前点为左端点 ,根据我们手中现在有的 0 的个数 就可以找到我们可以用0 去填补的最长连续子序列可以到哪个位置。  然后相减就是最大长度。

代码: 

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define N 100005

using namespace std;

int card[N];
int zero;
int n,m;

int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		cin>>n>>m;
		zero=0;
		int x;
		memset(card,0,sizeof(card));
		
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&x);
			if(x==0) zero++;
			card[x]++;
		}
		
		for(int i=1;i<=m;i++){
			if(card[i]){
				card[i]=card[i-1];
			}
			else{
				card[i]=card[i-1]+1;
			}
		}
		
		int ans=1;
		for(int i=1;i<=m;i++)
		{
			int ind=upper_bound(card+1,card+m+1,zero+card[i-1])-(card+1);
			ind++;
			ans=max(ans,ind-i);
		}
		
		printf("%d\n",ans);
		
		//cout<<ans<<endl;
	}
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值