AtCoder Grand Contest 017: C - Snuke and Spells

,

http://agc017.contest.atcoder.jp/tasks/agc017_c

反省

端から決めていく方向ばかり考えていた。 それが無理そうだというのは分かっていたが、ではどういうのなら解けるのかというのをちゃんと考えなかった。 区間のようなものは認識していたがきちんと区間として整理はしなかった。するべきだった。

implementation

#include <cstdio>
#include <vector>
#define repeat(i, n) for (int i = 0; (i) < int(n); ++(i))
using namespace std;

int main() {
    // input
    int n, m; scanf("%d%d", &n, &m);
    vector<int> a(n);
    repeat (i, n) {
        scanf("%d", &a[i]); -- a[i];
    }
    // prepare
    vector<int> cnt(n);
    vector<int> covered(n);
    int sum = 0;
    auto push = [&](int x) {
        cnt[x] += 1;
        int l = x + 1 - cnt[x];
        if (l >= 0) {
            if (covered[l] == 0) sum += 1;
            covered[l] += 1;
        }
    };
    auto pop = [&](int x) {
        int l = x + 1 - cnt[x];
        if (l >= 0) {
            covered[l] -= 1;
            if (covered[l] == 0) sum -= 1;
        }
        cnt[x] -= 1;
    };
    // serve
    repeat (i, n) {
        push(a[i]);
    }
    repeat (i, m) {
        int x, y; scanf("%d%d", &x, &y); -- x; -- y;
        pop(a[x]);
        a[x] = y;
        push(a[x]);
        printf("%d\n", n - sum);
    }
    return 0;
}