• FZU 2216 The Longest Straight(最长直道)


    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.

      ZB正在玩一个纸牌游戏叫做造直道。这幅卡组中的每张卡都有一个1到M间的数字(包括1与M)。一条直道是连续的卡牌序列。值不能循环,因此1不能在M后面。注意除了基本牌外,卡组里还有大小王。每张王可以当成任意一个有效数字(1到M,包括1与M)。

      给你N个整数card[1] .. card[n]表示你的手牌。大小王由0表示,其他牌由他们的值表示。ZB想知道自己手牌可以造出的直道最大长度是多少。

    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).

      输入的首行是一个整数T,表示测试样例的数量。

      对于每个测试样例:

      第一行有2个整数N和M(1 <= N, M <= 100000),并且第二行有N个整数card[i] (0 <= card[i] <= M)。

    Output

    输出

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

      对于每个测试样例,输出一行一个整数——ZB可以得到的最大直道长度。

    Sample Input - 输入样例

    Sample Output - 输出样例

    2

    7 11

    0 6 5 3 0 10 11

    8 1000

    100 100 100 101 100 99 97 103

    5

    3

    【题解】

      从数据来看,时间复杂度O(N2)必定爆炸(反正我没优化出来……),请使用O(Nlog2N)。

      因此推测出算法,确定左端点(N),二分查(log2N)找在鬼牌允许使用范围内的右端点。

      记录当前点前面有多少个0(空缺),然后两端一减就得到需要几张鬼牌填充了。

    【代码 C++】

      空间比较任性,速度还能优化……

     1 #include<cstdio>
     2 #include<cstring>
     3 int data[100005], sot[100005];
     4 int length(int L, int R, int i0){//[ L, R]
     5     if (L == R){
     6         if (sot[L] || i0) return 1;
     7         return 0;
     8     }
     9     int mid = L + R >> 1;
    10     if (data[mid] - data[L - 1] > i0) return length(L, mid, i0);
    11     return mid - L + 1 + length(mid + 1, R, i0 - (data[mid] - data[L - 1]));
    12 }
    13 int main(){
    14     int T, N, M, i, j, opt;
    15     scanf("%d", &T);
    16     while (T--){
    17         memset(sot, 0, sizeof(sot));
    18         scanf("%d%d", &N, &M);
    19         for (data[0] = i = 0; i < N; ++i) scanf("%d", &j), ++sot[j];
    20         for (i = 1; i <= M; ++i){
    21             if (sot[i]) data[i] = data[i - 1];
    22             else data[i] = data[i - 1] + 1;
    23         }
    24         for (opt = i = 1; i <= M; ++i){
    25             j = length(i, M, sot[0]);
    26             if (j>opt) opt = j;
    27         }
    28         printf("%d
    ", opt);
    29     }
    30     return 0;
    31 }

     FZU 2216

  • 相关阅读:
    Swift 编程语言新手教程
    标准差(standard deviation)和标准错误(standard error)你能解释一下?
    shell文字过滤程序(十一):paste命令
    java 获取系统变量(环境变量和环境变量)
    MD5算法原理
    受托停止事件冒泡
    搜索引擎优化要领:8条辅助技巧(三)
    几种更新(Update语句)查询的方法
    学习盲点
    2014年同年CFA考试中哪些CFA资料没有变化?
  • 原文地址:https://www.cnblogs.com/Simon-X/p/5153654.html
Copyright © 2020-2023  润新知