FOJ Problem 2216 The Longest Straight
2016-04-12 16:25
411 查看
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
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
题意:先说一下大概的题意,就是说给你一些牌,牌上有对应的数值,另外有一些joker,这些可以替换成任意数值的牌,让你用手上的牌(包括joker)构造出一段最长的连续序列
解题思路:以下代码的数据存储的的方法是用0, 1表示的,a[k]==1表示有k这张牌,反之则没有。首先一种最笨而一定能求出来的方法就是枚举起点i跟终点j,然后统计i到j之间的空缺数,若空缺数小于等于joker数量,记录i~j的区间长度,判断能否对Max经行更新。然后看一下m的数量达到100000,用这种方法枚举起点跟终点的复杂度为O(m*m),加上计算空缺数,总的时间复杂度高达O(m*m*m),超时是毫无疑问的。但并不代表这种方法不可行。首先先从统计i~j区间的空缺数上优化,在这边构造一个s数组,s[k]表示1~k的空缺数,那么i到j的空缺数直接就是s[j]-s[i-1],s的构造需要O(m),
构造完s后求空缺的时间复杂度为O(1),所以总的时间复杂度降为O(m*m), 但是对已m=100000还是超时的,所以看看时间复杂度能不能降到O(m)。现在回到i, j上面来,明白一点初始时j=i+Max, 然后在移动i, j的过程中有一点很关键就是当对i经行i++时,对应j一定要增大,即对应要有j++, 因为这样才能保证i~j的区间长度不小于Max,因为题目最终是要求i~j的最大区间长度,你再去计算比Max小的区间长度是没有必要的。另外j到达m时就要终止了, 应为joker只能变为1~m之间的数,这时候你考虑大于m的数是没有意义的。在这个过程中区间右端点是不断向右移动的,时间复杂度最终降为O(m),
所以可以通过了。
AC代码:
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
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
题意:先说一下大概的题意,就是说给你一些牌,牌上有对应的数值,另外有一些joker,这些可以替换成任意数值的牌,让你用手上的牌(包括joker)构造出一段最长的连续序列
解题思路:以下代码的数据存储的的方法是用0, 1表示的,a[k]==1表示有k这张牌,反之则没有。首先一种最笨而一定能求出来的方法就是枚举起点i跟终点j,然后统计i到j之间的空缺数,若空缺数小于等于joker数量,记录i~j的区间长度,判断能否对Max经行更新。然后看一下m的数量达到100000,用这种方法枚举起点跟终点的复杂度为O(m*m),加上计算空缺数,总的时间复杂度高达O(m*m*m),超时是毫无疑问的。但并不代表这种方法不可行。首先先从统计i~j区间的空缺数上优化,在这边构造一个s数组,s[k]表示1~k的空缺数,那么i到j的空缺数直接就是s[j]-s[i-1],s的构造需要O(m),
构造完s后求空缺的时间复杂度为O(1),所以总的时间复杂度降为O(m*m), 但是对已m=100000还是超时的,所以看看时间复杂度能不能降到O(m)。现在回到i, j上面来,明白一点初始时j=i+Max, 然后在移动i, j的过程中有一点很关键就是当对i经行i++时,对应j一定要增大,即对应要有j++, 因为这样才能保证i~j的区间长度不小于Max,因为题目最终是要求i~j的最大区间长度,你再去计算比Max小的区间长度是没有必要的。另外j到达m时就要终止了, 应为joker只能变为1~m之间的数,这时候你考虑大于m的数是没有意义的。在这个过程中区间右端点是不断向右移动的,时间复杂度最终降为O(m),
所以可以通过了。
AC代码:
# include <cstdio> # include <cstring> # include <algorithm> using namespace std; int s[100010], a[100010]; int main(){ int t, n, i, j, k, m, cnt, temp, Max; scanf("%d", &t); for(i=1; i<=t; i++){ scanf("%d%d", &n, &m); cnt=0; memset(a, 0, sizeof(a)); for(j=1; j<=n; j++){ scanf("%d", &temp); if(temp==0){ cnt++; } else{ a[temp]=1; } } s[0]=0; for(j=1; j<=m; j++){ if(a[j]==0){ s[j]=s[j-1]+1; } else{ s[j]=s[j-1]; } } Max=max(1, cnt); if(Max>m){ Max=m; } j=1;k=j+Max; while(k<=m){ if(s[k]-s[j-1]<=cnt){ Max=max(Max, k-j+1); k++; } else{ j++;k++; } } printf("%d\n", Max); } return 0; }
相关文章推荐
- 【mdadm】将任何块设备做成RAID
- diff 命令 expain
- 关于中国人工智能学会的分支机构改革与面向未来的几个问题
- uva 10245 The Closest Pair Problem
- 【tail】查看文件后n行
- mfcs100d.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in MSVCRTD.lib(dllmain.obj)
- 配置View桌面时找不到域的解决方法
- “RegSvr32 failed with exit code 0x3”问题的解决办法
- 清华教授谈人工智能:BAT还算不上伟大公司
- log4j启动时警告:SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
- Foxmail设置Gmail邮箱
- HashSet---Contains Duplicate
- CodeForces 606C--Sorting Railway Cars,思路题~~~
- AIX 操作系统安装
- AIX 安装标准
- poj 3691 DNA repair AC自动机+DP
- U-Mail反垃圾邮件网关过滤Locky勒索邮件
- U-Mail反垃圾邮件网关过滤Locky勒索邮件
- AIX root 密码丢失解决办法
- LeetCode196. Delete Duplicate Emails