Submission #705015

#TimeUsernameProblemLanguageResultExecution timeMemory
705015CyanmondFinancial Report (JOI21_financial)C++17
100 / 100
606 ms46996 KiB
#include <bits/stdc++.h>

constexpr int inf = 1 << 30;

class SegTree {
    int n, size;
    std::vector<int> data;
    void update(int i) {
        data[i] = std::max(data[2 * i], data[2 * i + 1]);
    }

    public:
    SegTree(int n_) : n(n_) {
        size = 1;
        while (size < n) size *= 2;
        data.assign(2 * size, -inf);
    }

    void set(int i, int v) {
        i += size;
        data[i] = v;
        while (i != 1) {
            i /= 2;
            update(i);
        }
    }

    int fold(int l, int r) {
        int res = -inf;
        for (l += size, r += size; l < r; l >>= 1, r >>= 1) {
            if (l & 1) res = std::max(res, data[l++]);
            if (r & 1) res = std::max(res, data[--r]);
        }
        return res;
    }

    int get(int i) {
        return data[i + size];
    }
};

int solve(int D, std::vector<int> A) {
    const int N = (int)A.size();
    {
        // press
        auto B = A;
        std::sort(B.begin(), B.end());
        B.erase(std::unique(B.begin(), B.end()), B.end());
        for (auto &e : A) e = (int)(std::lower_bound(B.begin(), B.end(), e) - B.begin()) + 1;
    }

    std::vector<std::vector<int>> posList(N + 1);
    for (int i = 0; i < N; ++i) {
        posList[A[i]].push_back(i);
    }
    std::vector<int> keepLimit(N, N);
    std::set<int> sids;
    for (int i = D; i < N; ++i) sids.insert(i);
    for (int v = 1; v <= N; ++v) {
        for (const int i : posList[v]) {
            // [i + 1, i + D]
            auto itr = sids.upper_bound(i);
            while (itr != sids.end() and *itr <= i + D) {
                itr = sids.erase(itr);
            }
        }
        for (const int i : posList[v]) {
            auto itr = sids.upper_bound(i);
            if (itr != sids.end()) {
                keepLimit[i] = *itr;
            }
        }
    }

    SegTree seg(N + 1);
    seg.set(0, 0);
    std::vector<std::vector<int>> eraseList(N + 1);
    for (int i = 0; i < N; ++i) {
        for (const int j : eraseList[i]) {
            seg.set(j, -inf);
        }
        const int f = seg.fold(0, A[i]);
        seg.set(A[i], std::max(seg.get(A[i]), f + 1));
        eraseList[keepLimit[i]].push_back(A[i]);
    }
    return seg.fold(0, N + 1);
}

int solveNaive(int D, std::vector<int> A) {
    const int N = (int)A.size();
    int answer = 1;
    for (int bits = 0; bits < (1 << N); ++bits) {
        int last = -1;
        if (not(bits & (1 << (N - 1)))) {
            continue;
        }
        int res = 0, ma = -1;
        for (int i = 0; i < N; ++i) {
            if (bits & (1 << i)) {
                if (last == -1) {
                    last = i;
                } else {
                    if (i - last > D) {
                        res = -1;
                        break;
                    }
                }
                last = i;
                if (A[i] > ma) {
                    ++res;
                    ma = A[i];
                }
            }
        }
        answer = std::max(answer, res);
    }
    return answer;
}

int main() {
    int N, D;
    std::cin >> N >> D;
    std::vector<int> A(N);
    for (auto &e : A) {
        std::cin >> e;
    }
    std::cout << solve(D, A) << std::endl;
    /*
    int N = 15;
    int cas = 100;
    std::mt19937 mt(100);
    std::uniform_int_distribution dist(1, N);
    while (cas--) {
        std::vector<int> A(N);
        for (auto &e : A) e = dist(mt);
        int D = dist(mt);
        const int a = solveNaive(D, A), b = solve(D, A);
        if (a != b) {
            std::cout << D << std::endl;
            for (const auto e : A) std::cout << e << ' ';
            std::cout << std::endl;
        }
    }*/
}
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...