Problem:
最長の階段

問題

1 から n までの整数がそれぞれ 1 つずつ書かれた n 枚のカードと,1 枚の白紙の
カードがある.これら n + 1 枚のカードの内,k 枚のカードが与えられる.ただし,
1 ≤ k ≤ n である.白紙のカードには 1 から n までの整数を 1 つ書くことができ
る.与えられたカードだけで,できるだけ長い連続した整数列を作りたい.

与えられるカードが入力されたときに, 与えられたカードから作ることができる連
続した整数列の最大長を出力するプログラムを作成せよ.

例1

n = 7, k = 5 とする.6, 2, 4, 7, 1 のカードが与えられたとき,このカードを使っ
て作れる連続した整数列のうち最長のものは 1, 2 であり,その長さは 2 である.

例2

n = 7, k = 5 とする.6, 2, 4, 7 と白紙のカードが与えられたとき,このカードを
使って作れる連続した整数列のうち最長のものは,白紙のカードに 5 を書くことに
よってできる 4, 5, 6, 7 であり,その長さは 4 である.

入力

入力は複数のデータセットからなる．各データセットは以下の形式で与えられる．入力はゼロ２つを含む行で終了する．

1 行目には,2 つの整数 n (1 ≤ n ≤ 100000) と k (1 ≤ k ≤ n) がこの順で 1 つの
空白を区切りとして書かれている.続く k 行には整数が 1 つずつ書かれており,与
えられる k 枚のカードに書かれている整数を表している.白紙のカードは 0 で表さ
れる.

採点用データのうち, 配点の 40% 分は 1 ≤ n ≤ 1000, 1 ≤ k ≤ 500 を, 配点の 20% 分は 1 ≤ n ≤ 60000, 1 ≤ k ≤ 50000 を. 配点の 40% 分は 1 ≤ n ≤ 100000, 1 ≤ k ≤ 100000 を満たす.

データセットの数は 5 を超えない．

出力

データセットごとに整数を1行に出力する．

入出力例

入力例

7 5
6
2
4
7
1
7 5
6
2
0
4
7
0 0

出力例

2
4

上記問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。

Solution in C++14 (judge verdict: Accepted)

#include <iostream>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <map>
#include <queue>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using namespace std;

template<class T>
constexpr T INF = ::numeric_limits<T>::max() / 32 * 15 + 208;

int main() {
    int n, k;
    while (cin >> n >> k, n|k){
        map<int, int> m;
        vector<pair<int, int>> c;
        for (int i = 0; i < k; ++i) {
            int x;
            scanf("%d", &x);
            m[x]++;
        }
        int w = m[0];
        int s = 0, g = 0, ans = 1;
        for (int i = 1; i <= n+1; ++i) {
            if(m[i]) {
                if(s == 0) s = i;
                g = i;
            }
            else  {
                if(s != 0 && g != 0) {
                    ans = max(ans, w+g-s+1);
                    c.emplace_back(s, g);
                }
                s = 0, g = 0;
            }
        }
        if(w) {
            for (int i = 0; i < c.size()-1; ++i) {
                if(c[i+1].first-c[i].second == 2){
                    ans = max(ans, c[i+1].second-c[i].first+1);
                }
            }
        }
        cout << ans << "\n";
    } 
    
    return 0;
}