Problem:
日本沈没 (Japan Sinks)

問題文

日本列島は細長い列島である．日本列島は平行な境界線により N 個の区画に分けられている．区画には端から順に 1 から N の番号が付けられている．区画 i (1 ≦ i ≦ N) の高さは A_i である．

日本列島は海に囲まれており，海面の高さは場所によらず一定である．高さが海面の高さより高い区画を陸地と呼ぶ．

陸地が連続している部分のことを島と呼ぶ．より正確に書くと以下の通りである．整数 l, r (1 ≦ l ≦ r ≦ N) について，日本列島のうち区画 l，区画 l+1，...，区画 r からなる部分を領域 [l, r] という．以下の条件を満たす領域 [l, r] を島という：

区画 l，区画 l+1，...，区画 r はすべて陸地である．

l>1 ならば区画 l-1 は陸地ではない．

r<N ならば区画 r+1 は陸地ではない．

海面の上昇により，日本列島は少しずつ沈没している．現在の海面の高さは 0 であるが，これは時間が経つにつれて徐々に上がり，ついには日本全体が海になってしまう．

JOI 君は，海面の高さが上昇すると，日本の島の数が増減することに気付いた．現在から，日本に陸地がなくなるまでの間 (現在も含む) における，島の数の最大値を求めたい．

制約

1 ≦ N ≦ 100000 (= 10^5)

0 ≦ A_i ≦ 1000000000 (= 10^9) (1 ≦ i ≦ N)

入力・出力

入力

入力は以下の形式で標準入力から与えられる．

N

A_1 A_2 ... A_N

出力

現在から，日本に陸地がなくなるまでの間 (現在も含む) における，島の数の最大値を 1 行で出力せよ．

入出力例

入力例 1

6
0 1 2 1 3 2

出力例 1

2

海面の高さが 0 以上 1 未満のとき，区画 2, 3, 4, 5, 6 が陸地である．領域 [2, 6] が唯一の島なので，島の数は 1 である．

海面の高さが 1 以上 2 未満のとき，区画 3, 5, 6 が陸地である．領域 [3, 3] と領域 [5, 6] が島なので，島の数は 2 である．

海面の高さが 2 以上 3 未満のとき，区画 5 のみが陸地である．領域 [5, 5] が唯一の島なので，島の数は 1 である．

海面の高さが 3 になると，陸地はなくなり，島の数は 0 になる．

よって島の数の最大値は 2 なので，2 を出力する．

入力例 2

6
3 2 3 0 2 0

出力例 2

2

海面の高さが 0 以上 2 未満のとき，区画 1, 2, 3, 5 が陸地である．領域 [1, 3] と領域 [5, 5] が島なので，島の数は 2 である．

海面の高さが 2 以上 3 未満のとき，区画 1, 3 が陸地である．領域 [1, 1] と領域 [3, 3] が島なので，島の数は 2 である．

海面の高さが 3 になると，陸地はなくなり，島の数は 0 になる．

よって島の数の最大値は 2 なので，2 を出力する．

入力例 3

10
4 1 2 1 2 3 5 4 3 2

出力例 3

3

情報オリンピック日本委員会作 『第 18 回日本情報オリンピック JOI 2018/2019 予選競技課題』

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

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;

int main() {
    int N;
    cin >> N;
    vector<int> A(N);

    for(int i = 0; i < N; i++) {
        cin >> A[i];
    }

    vector<bool> sea(N+2);
    sea[0] = true;
    sea[N+1] = true;
    vector<pair<int, int>> AandNum;

    /*初期状態での陸地と海を調べる*/
    for(int i = 0; i < N; i++) {
        if(A[i] == 0) {
            sea[i+1] = true;
        }
        else {
            /*陸地の場合は高さと配列のインデックスを記録*/
            AandNum.push_back(make_pair(A[i], i+1)); 
            sea[i+1] = false;
        }
    }
    
    /*陸地の高さの順にソート*/
    sort(AandNum.begin(), AandNum.end());

    int temp = 0;
    int ans = 0;
    /*島の数の初期状態をカウント*/
    for(int i = 0; i < N+1; i++) {
        if(sea[i] && !sea[i+1]) {
            temp += 1;
        }
    }
    ans = temp;
    /*陸地が一つ沈んだ場合の島の増減*/
    for(int i = 0; i < AandNum.size(); i++) {
        int j = AandNum[i].second;
        sea[j] = true;
        /*両方が陸地なら島が1つ増える*/
        if(!sea[j-1] && !sea[j+1]) {
            temp += 1;
        }
        /*両方が海なら島が1つ減る*/
        else if(sea[j-1] && sea[j+1]) {
            temp -= 1;
        }
        if(i+1 == AandNum.size() || AandNum[i].first < AandNum[i+1].first) {
            ans = max(ans, temp);
        }
    }
    cout << ans << endl;

    return 0;
}