Submission #1279209

#TimeUsernameProblemLanguageResultExecution timeMemory
1279209MisterReaperRope (JOI17_rope)C++20
100 / 100
1916 ms117224 KiB
// File rope.cpp created on 14.10.2025 at 17:22:16
#include <bits/stdc++.h>

using i64 = long long;

#ifdef DEBUG 
    #include "/home/ahmetalp/Desktop/Workplace/debug.h"
#else
    #define debug(...) void(23)
#endif

#define def int mid = (l + r) >> 1, lv = v + 1, rv = v + ((mid - l + 1) << 1)

struct segtree {
    struct node {
        int sm = 0;
        int mx = 0;
        void modify(int x) {
            sm += x;
            mx += x;
        }
    };
    node unite(const node lhs, const node rhs) {
        node res;
        res.sm = lhs.sm + rhs.sm;
        res.mx = std::max(lhs.mx, rhs.mx);
        return res;
    }
    int n;
    std::vector<node> tree;
    segtree(int n_) : n(n_), tree(n << 1) {}
    void modify(int v, int l, int r, int p, int x) {
        if (l == r) {
            tree[v].modify(x);
            return;
        }
        def;
        if (p <= mid) {
            modify(lv, l, mid, p, x);
        } else {
            modify(rv, mid + 1, r, p, x);
        }
        tree[v] = unite(tree[lv], tree[rv]);
    }
    void modify(int p, int x) {
        modify(0, 0, n - 1, p, x);
    }
    node get(int v, int l, int r, int ql, int qr) {
        if (ql == l && r == qr) {
            return tree[v];
        }
        def;
        if (qr <= mid) {
            return get(lv, l, mid, ql, qr);
        } else if (mid + 1 <= ql) {
            return get(rv, mid + 1, r, ql, qr);
        } else {
            return unite(get(lv, l, mid, ql, mid),
                            get(rv, mid + 1, r, mid + 1, qr));
        }
    }
    node get(int l, int r) {
        return get(0, 0, n - 1, l, r);
    }
};

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int N, M;
    std::cin >> N >> M;

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

    std::vector<int> overall(N);
    for (int i = 0; i < N; ++i) {
        overall[A[i]] += 1;
    }

    // 1: First is single
    // 2: First and second is united
    int now1 = 0, now2 = 0;
    segtree cnt1(M), cnt2(M);
    std::vector<int> bad1(N), bad2(N);
    std::vector<int> typ1(N, 1), typ2(N, 1);
    auto Modify1 = [&](int p, int x) { 
        int id = (p + 1) / 2;
        {
            if (id == 0 || (N % 2 == 0 && id == N / 2)) {
                if (bad1[id] == 0) {
                    // ok
                } else {
                    cnt1.modify(A[p], -1);
                }
            } else {
                if (bad1[id] == 0) {
                    // ok
                } else if (bad1[id] == 1) {
                    now1 -= 1;
                } else {
                    cnt1.modify(A[2 * id - 1], -1);
                    cnt1.modify(A[2 * id], -1);
                }
            }
            bad1[id] -= !typ1[p];
        }
        typ1[p] = x;
        {
            bad1[id] += !typ1[p];
            if (id == 0 || (N % 2 == 0 && id == N / 2)) {
                if (bad1[id] == 0) {
                    // ok
                } else {
                    cnt1.modify(A[p], +1);
                }
            } else {
                if (bad1[id] == 0) {
                    // ok
                } else if (bad1[id] == 1) {
                    now1 += 1;
                } else {
                    cnt1.modify(A[2 * id - 1], +1);
                    cnt1.modify(A[2 * id], +1);
                }
            }
        }
    };
    auto Modify2 = [&](int p, int x) { 
        int id = p / 2;
        {
            if (N % 2 == 1 && id == (N - 1) / 2) {
                if (bad2[id] == 0) {
                    // ok
                } else {
                    cnt2.modify(A[p], -1);
                }
            } else {
                if (bad2[id] == 0) {
                    // ok
                } else if (bad2[id] == 1) {
                    now2 -= 1;
                } else {
                    cnt2.modify(A[2 * id], -1);
                    cnt2.modify(A[2 * id + 1], -1);
                }
            }
            bad2[id] -= !typ2[p];
        }
        typ2[p] = x;
        {
            bad2[id] += !typ2[p];
            if (N % 2 == 1 && id == (N - 1) / 2) {
                if (bad2[id] == 0) {
                    // ok
                } else {
                    cnt2.modify(A[p], +1);
                }
            } else {
                if (bad2[id] == 0) {
                    // ok
                } else if (bad2[id] == 1) {
                    now2 += 1;
                } else {
                    cnt2.modify(A[2 * id], +1);
                    cnt2.modify(A[2 * id + 1], +1);
                }
            }
        }
    };

    for (int i = 0; i < N; ++i) {
        Modify1(i, 0);
        Modify2(i, 0);
    }

    std::vector<std::vector<int>> ids(M);
    for (int i = 0; i < N; ++i) {
        ids[A[i]].emplace_back(i);
    }

    for (int c = 0; c < M; ++c) {
        int ans = N - overall[c];
        if (c != 0) {
            for (auto i : ids[c - 1]) {
                Modify1(i, 0);
                Modify2(i, 0);
            }
        }
        for (auto i : ids[c]) {
            Modify1(i, 1);
            Modify2(i, 1);
        }
        debug(c);
        debug(typ1);
        debug(typ2);
        debug(bad1);
        debug(bad2);
        auto nd1 = cnt1.get(0, M - 1);
        auto nd2 = cnt2.get(0, M - 1);
        debug(now1, nd1.sm, nd1.mx);
        #ifdef DEBUG
            for (int i = 0; i < M; ++i) {
                auto nd = cnt1.get(i, i);
                std::cerr << nd.sm << " \n"[i == M - 1];
            }
        #endif
        debug(now2, nd2.sm, nd2.mx);
        #ifdef DEBUG
            for (int i = 0; i < M; ++i) {
                auto nd = cnt2.get(i, i);
                std::cerr << nd.sm << " \n"[i == M - 1];
            }
        #endif
        ans = std::min(ans, now1 + nd1.sm - nd1.mx);
        ans = std::min(ans, now2 + nd2.sm - nd2.mx);
        std::cout << ans << '\n';
    }

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...