제출 #1182108

#제출 시각아이디문제언어결과실행 시간메모리
1182108cpdreamer서열 (APIO23_sequence)C++20
100 / 100
1724 ms79268 KiB
#include "sequence.h"
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define P pair
#define F first
#define all(v) v.begin(),v.end()
#define V vector
#define pb push_back
#define S second
const ll MOD = (ll)1e9 + 7;

struct segtree {
private:
    struct node {
        int mind, maxd;
    };

    node single(int v) {
        return {v, v};
    }

    node neutral = {INT_MAX, INT_MIN};

    node merge(node a, node b) {
        return {min(a.mind, b.mind), max(a.maxd, b.maxd)};
    }

    node apply(node a, int v) {
        return {a.mind + v, a.maxd + v};
    }

    void push(int x, int lx, int rx) {
        if (rx - lx == 1 || operation[x] == 0) return;
        int v = operation[x];
        query[2 * x + 1] = apply(query[2 * x + 1], v);
        query[2 * x + 2] = apply(query[2 * x + 2], v);
        operation[2 * x + 1] += v;
        operation[2 * x + 2] += v;
        operation[x] = 0;
    }

public:
    int size;
    V<node> query;
    V<int> operation;

    void init(int n) {
        size = 1;
        while (size < n) size *= 2;
        query.assign(2 * size, neutral);
        operation.assign(2 * size, 0);
    }

    void build(V<int> &a, int x, int lx, int rx) {
        if (rx - lx == 1) {
            if (lx < (int)a.size()) {
                query[x] = single(a[lx]);
            }
            return;
        }
        int m = (lx + rx) / 2;
        build(a, 2 * x + 1, lx, m);
        build(a, 2 * x + 2, m, rx);
        query[x] = merge(query[2 * x + 1], query[2 * x + 2]);
    }

    void build(V<int> &a) {
        build(a, 0, 0, size);
    }

    void set(int l, int r, int v, int x, int lx, int rx) {
        push(x, lx, rx);
        if (lx >= r || rx <= l) return;
        if (l <= lx && rx <= r) {
            query[x] = apply(query[x], v);
            operation[x] += v;
            return;
        }
        int m = (lx + rx) / 2;
        set(l, r, v, 2 * x + 1, lx, m);
        set(l, r, v, 2 * x + 2, m, rx);
        query[x] = merge(query[2 * x + 1], query[2 * x + 2]);
    }

    void set(int l, int r, int v) {
        set(l, r, v, 0, 0, size);
    }

    node calc(int l, int r, int x, int lx, int rx) {
        push(x, lx, rx);
        if (rx <= l || lx >= r) return neutral;
        if (l <= lx && rx <= r) return query[x];
        int m = (lx + rx) / 2;
        node a = calc(l, r, 2 * x + 1, lx, m);
        node b = calc(l, r, 2 * x + 2, m, rx);
        return merge(a, b);
    }

    int mind(int l, int r) {
        return calc(l, r, 0, 0, size).mind;
    }

    int maxd(int l, int r) {
        return calc(l, r, 0, 0, size).maxd;
    }
};

bool inter(P<int, int> a, P<int, int> b) {
    if (a.F > b.F) swap(a, b);
    return a.S >= b.F;
}

int f(int N, V<int> A) {
    V<int> a(N + 1), occ(N + 1);
    V<V<int>> pos(N + 1);
    set<int> st;
    for (int i = 1; i <= N; i++) {
        a[i] = A[i - 1];
        occ[a[i]]++;
        pos[a[i]].pb(i);
        st.insert(a[i]);
    }

    V<int> d(all(st));
    V<int> b = a;
    sort(all(b));
    int ans = max(occ[b[(N + 1) / 2]], occ[b[(N + 2) / 2]]);
    V<int> vp(N + 1);
    vp[0] = 0;
    for (int i = 1; i <= N; i++) vp[i] = vp[i - 1] + 1;

    segtree tree;
    tree.init(N + 2);
    tree.build(vp);

    for (auto u : d) {
        V<P<P<int, int>, P<int, int>>> q;
        int sz = (int)pos[u].size();
        for (int i = 0; i < sz; i++) {
            int mnl = tree.mind(0, pos[u][i] + 1);
            int mxl = tree.maxd(0, pos[u][i] + 1);
            int mnr = tree.mind(pos[u][i], N + 1);
            int mxr = tree.maxd(pos[u][i], N + 1);
            q.pb({{mnl, mxl}, {mnr, mxr}});
        }
        int l = 1, r = N;
        while (l <= r) {
            int m = (l + r) / 2;
            bool flag = false;
            for (int i = 0; i + m - 1 < sz; i++) {
                P<int, int> p1 = {q[i].F.F, q[i].F.S};
                P<int, int> p2 = {q[i + m - 1].S.F, q[i + m - 1].S.S};
                if (inter(p1, p2)) flag = true;
            }
            if (flag) {
                ans = max(ans, m);
                l = m + 1;
            } else {
                r = m - 1;
            }
        }
        for (int i = 0; i < sz; i++) {
            tree.set(pos[u][i], N + 1, -2);
        }
        q.clear();
        for (int i = 0; i < sz; i++) {
            int mnl = tree.mind(0, pos[u][i] + 1);
            int mxl = tree.maxd(0, pos[u][i] + 1);
            int mnr = tree.mind(pos[u][i], N + 1);
            int mxr = tree.maxd(pos[u][i], N + 1);
            q.pb({{mnl, mxl}, {mnr, mxr}});
        }
        l = 1, r = N;
        while (l <= r) {
            int m = (l + r) / 2;
            bool flag = false;
            for (int i = 0; i + m - 1 < sz; i++) {
                P<int, int> p1 = {q[i].F.F, q[i].F.S};
                P<int, int> p2 = {q[i + m - 1].S.F, q[i + m - 1].S.S};
                if (inter(p1, p2)) flag = true;
            }
            if (flag) {
                ans = max(ans, m);
                l = m + 1;
            } else {
                r = m - 1;
            }
        }
    }

    return ans;
}

int sequence(int N, std::vector<int> A) {
    return f(N, A);
}
#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...