제출 #1335406

#제출 시각아이디문제언어결과실행 시간메모리
1335406PakinDioxide서열 (APIO23_sequence)C++17
70 / 100
2131 ms474964 KiB
#include "sequence.h"
#include <bits/stdc++.h>
#define ll long long

using namespace std;

const int mxN = 5e5+5;

int N;

struct PST {
    int seg[mxN], it = 0;
    struct {
        int val, L, R, l, r; // L is expand to left
    } pool[mxN << 5];

    int nw(int x) {
        pool[++it] = {x, max(x, 0), max(x, 0), 0, 0};
        return it;
    }

    int nw(int l, int r) {
        pool[++it] = {pool[l].val + pool[r].val, 
            max({0, pool[l].L + pool[r].val, pool[r].L}),
            max({0, pool[r].R + pool[l].val, pool[l].R}),
            l, r};
        return it;
    }

    int build(int l, int r, int x) {
        if (l == r) return nw(x);
        else {
            int m = l + (r-l)/2;
            return nw(build(l, m, x), build(m+1, r, x));
        }
    }

    int upd(int l, int r, int idx, int x, int u) {
        if (l == r) return nw(x);
        else {
            int m = l + (r-l)/2;
            if (m >= idx) return nw(upd(l, m, idx, x, pool[u].l), pool[u].r);
            else return nw(pool[u].l, upd(m+1, r, idx, x, pool[u].r));
        }
    }

    int QR(int l, int r, int x, int y, int u) {
        if (x <= l && r <= y) return pool[u].val;
        else {
            int m = l + (r-l)/2, k = 0;
            if (m >= x) k += QR(l, m, x, y, pool[u].l);
            if (m+1 <= y) k += QR(m+1, r, x, y, pool[u].r);
            return k;
        }
    }

    pair <int, int> QR_l(int l, int r, int idx, int u) {
        if (idx < 0 || idx >= N) return make_pair(0, 0);
        if (r <= idx) return make_pair(pool[u].L, pool[u].val);
        else {
            int m = l + (r-l)/2;
            if (idx <= m) return QR_l(l, m, idx, pool[u].l);
            pair <int, int> B = QR_l(m+1, r, idx, pool[u].r);
            return make_pair(max({0, pool[pool[u].l].L + B.second, B.first}), pool[pool[u].l].val + B.second);
        }
    }

    pair <int, int> QR_r(int l, int r, int idx, int u) {
        if (idx < 0 || idx >= N) return make_pair(0, 0);
        if (l >= idx) return make_pair(pool[u].R, pool[u].val);
        else {
            int m = l + (r-l)/2;
            if (idx > m) return QR_r(m+1, r, idx, pool[u].r);
            pair <int, int> B = QR_r(l, m, idx, pool[u].l);
            return make_pair(max({0, pool[pool[u].r].R + B.second, B.first}), pool[pool[u].r].val + B.second);
        }
    }
} T, T2;

int sequence(int n, vector <int> A) {
    N = n;
    T.seg[0] = T.build(0, N-1, -1);
    T2.seg[0] = T2.build(0, N-1, 1);
    vector <pair <int, int>> V;
    for (int i = 0; i < N; i++) V.emplace_back(A[i], i);
    V.emplace_back(0, 0);
    sort(V.begin(), V.end());
    int prev[N+1]; memset(prev, 0, sizeof(prev));
    for (int i = 1; i <= N; i++) {
        if (i == 1 || V[i].first != V[i-1].first) prev[V[i].first] = V[i-1].first;
        T.seg[V[i].first] = T.upd(0, N-1, V[i].second, 1, T.seg[V[i-1].first]);
        T2.seg[V[i].first] = T2.upd(0, N-1, V[i].second, -1, T2.seg[V[i-1].first]);
    }
    vector <int> a[N+1];
    int ID[N];
    for (int i = 0; i < N; i++) a[A[i]].emplace_back(i), ID[i] = a[A[i]].size() - 1;
    int l = 0, r = 0, ans = 0;
    for (int i = 1; i <= N; i++) r = max(r, (int) a[i].size());
    int can[N]; for (auto &e : can) e = INT_MAX;
    while (l <= r) {
        int x = l + (r-l)/2;
        int ok = 0;
        for (int i = 0; i < N; i++) if (can[i] > x) {
            // for (int j = 0; j < N; j++) cout << T.QR(0, N-1, j, j, T.seg[A[i]]) << ' '; cout << '\n';
            int idx = ID[i];
            if (idx + x - 1 >= (int) a[A[i]].size()) { can[i] = x; continue; }
            idx += x - 1;
            idx = a[A[i]][idx];
            int fx = T.QR(0, N-1, i, idx, T.seg[prev[A[i]]]) + T.QR(0, N-1, i, idx, T.seg[A[i]]);
            assert(fx % 2 == 0);
            fx /= 2;
            int MX = T.QR_l(0, N-1, i-1, T.seg[A[i]]).first + T.QR_r(0, N-1, idx+1, T.seg[A[i]]).first;
            // cout << T.QR_l(0, N-1, i-1, T.seg[A[i]]).first << ' ';
            // cout << T.QR_r(0, N-1, idx+1, T.seg[A[i]]).first << '\n';
            // cout << MX << '\n';
            int MN = -(T2.QR_l(0, N-1, i-1, T.seg[prev[A[i]]]).first + T2.QR_r(0, N-1, idx+1, T.seg[prev[A[i]]]).first);
            // cout << MX << ' ' << MN << ' ' << fx << '\n';
            MX += fx;
            MN += fx;
            // cout << x << ' ' << i << ' ' << idx << '\n';
            if (!(MX < -x || MN > x)) { ok = 1; break; }
            else can[i] = x;
        }
        if (ok == 1) ans = x, l = x+1;
        else r = x-1;
    }
    return ans;
}
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...