Submission #751738

#TimeUsernameProblemLanguageResultExecution timeMemory
751738Desh03Sequence (APIO23_sequence)C++17
40 / 100
2170 ms1757300 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

template<typename T>
using oset = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

struct SegmentTree {
    struct node {
        int mn, h, d, delta;
        node *left, *right;
        node() : h(0), d(0), mn(0), delta(0), left(NULL), right(NULL) { };
        void pull() {
            mn = min(left->mn, right->mn);
        }
        void push(int l, int r) {
            int m = l + r >> 1;
            if (left == NULL) left = new node();
            if (right == NULL) right = new node();
            if (h != -1) {
                left->h = h;
                left->d = d;
                right->h = h + (m - l + 1) * d;
                right->d = d;
                if (d > 0) {
                    left->mn = left->h;
                    right->mn = right->h;
                } else {
                    left->mn = h + (m - l) * d;
                    right->mn = h + (r - l) * d;
                }
                h = -1;
                delta = 0;
            }
            if (delta) {
                left->mn += delta;
                if (left->h != -1) left->h += delta;
                else left->delta += delta;
                right->mn += delta;
                if (right->h != -1) right->h += delta;
                else right->delta += delta;
                delta = 0;
            }
        }
    } *root;
    int n;
    void upd(node* &v, int l, int r, int ql, int qr, int h, int d) {
        if (l > qr || r < ql) return;
        if (l >= ql && r <= qr) {
            v->delta = 0;
            v->h = h + (l - ql + 1) * d, v->d = d;
            v->mn = d > 0 ? v->h : v->h + (r - l) * d;
            return;
        }
        v->push(l, r);
        int m = l + r >> 1;
        upd(v->left, l, m, ql, qr, h, d);
        upd(v->right, m + 1, r, ql, qr, h, d);
        v->pull();
    }
    void upd2(node* &v, int l, int r, int ql, int qr, int delta) {
        if (l > qr || r < ql) return;
        if (l >= ql && r <= qr) {
            v->mn += delta;
            if (v->h != -1) v->h += delta;
            else v->delta += delta;
            return;
        }
        v->push(l, r);
        int m = l + r >> 1;
        upd2(v->left, l, m, ql, qr, delta);
        upd2(v->right, m + 1, r, ql, qr, delta);
        v->pull();
    }
    int find_first(node* &v, int l, int r, int h) {
        if (l == r) return l;
        v->push(l, r);
        int m = l + r >> 1;
        if (v->left->mn < h) return find_first(v->left, l, m, h);
        return find_first(v->right, m + 1, r, h);
    }
    int qry(node* &v, int l, int r, int u) {
        if (l == r) return v->mn;
        v->push(l, r);
        int m = l + r >> 1;
        if (u <= m) return qry(v->left, l, m, u);
        return qry(v->right, m + 1, r, u);
    }
    SegmentTree() : root(NULL) { };
    SegmentTree(int n_) : root(new node()), n(n_) { }; // Declares an array of size n with initial elements zero, zero-based indexing.
    int qry(int u) { // Returns the element at index u.
        if (u < 0 || u > n - 1) return 0;
        return qry(root, 0, n - 1, u);
    }
    int find_first(int h) { // Returns the index of the first element < h in the array, or -1 if no such element exists.
        if (root->mn >= h) return -1;
        return find_first(root, 0, n - 1, h);
    }
    void upd(int l, int r, int h, int d) { // Assigns an arithmetic progression h + id to elements in range [l, r], i = 1, 2, 3, ..., r - l + 1.
        if (l > r) return;
        upd(root, 0, n - 1, l, r, h, d);
    }
    void upd2(int l, int r, int delta) { // Adds delta to elements in range [l, r].
        if (l > r) return;
        upd2(root, 0, n - 1, l, r, delta);
    }
} s[500000], pre[500000];

int sequence(int n, vector<int> a) {
    int ans = 0;
    if (n <= 3e3) {
        oset<pair<int, int>> s;
        vector<int> f(n + 1);
        for (int i = 0; i < n; i++) {
            for (int j = i; j < n; j++) {
                s.insert({a[j], j});
                ++f[a[j]];
                int med1 = (*s.find_by_order((j - i) / 2)).first, med2 = (*s.find_by_order((j - i + 1) / 2)).first;
                ans = max(ans, max(f[med1], f[med2]));
            }
            s.clear();
            f = vector<int> (n + 1);
        }
        return ans;
    } else {
        for (int i = 0; i < n; i++) s[i] = SegmentTree(n), pre[i] = SegmentTree(n);
        for (int i = 0; i < n; i++) s[i].upd(0, n - 1, 1, -1);
        for (int i = 0; i < n; i++) {
            --a[i];
            pre[a[i]].upd2(i, n - 1, 1);
            s[a[i]].upd(i, i, 2 * pre[a[i]].qry(i - 1) - i + 1, -1);
            s[a[i]].upd(i + 1, n - 1, 2 * pre[a[i]].qry(i) - i, -1);
        }
        for (int i = 0; i < n; i++) {
            int l = s[a[i]].find_first(2 * pre[a[i]].qry(i) - i);
            if (l == -1 || l > i) continue;
            ans = max(ans, pre[a[i]].qry(i) - pre[a[i]].qry(l - 1));
        }
        sort(a.begin(), a.end());
        return max(ans, (a[n >> 1] == 1 || a[(n - 1) >> 1] == 1 ? pre[1].qry(n - 1) : 0));
    }
}

Compilation message (stderr)

sequence.cpp: In constructor 'SegmentTree::node::node()':
sequence.cpp:12:20: warning: 'SegmentTree::node::d' will be initialized after [-Wreorder]
   12 |         int mn, h, d, delta;
      |                    ^
sequence.cpp:12:13: warning:   'int SegmentTree::node::mn' [-Wreorder]
   12 |         int mn, h, d, delta;
      |             ^~
sequence.cpp:14:9: warning:   when initialized here [-Wreorder]
   14 |         node() : h(0), d(0), mn(0), delta(0), left(NULL), right(NULL) { };
      |         ^~~~
sequence.cpp: In member function 'void SegmentTree::node::push(int, int)':
sequence.cpp:19:23: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   19 |             int m = l + r >> 1;
      |                     ~~^~~
sequence.cpp: In member function 'void SegmentTree::upd(SegmentTree::node*&, int, int, int, int, int, int)':
sequence.cpp:58:19: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   58 |         int m = l + r >> 1;
      |                 ~~^~~
sequence.cpp: In member function 'void SegmentTree::upd2(SegmentTree::node*&, int, int, int, int, int)':
sequence.cpp:72:19: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   72 |         int m = l + r >> 1;
      |                 ~~^~~
sequence.cpp: In member function 'int SegmentTree::find_first(SegmentTree::node*&, int, int, int)':
sequence.cpp:80:19: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   80 |         int m = l + r >> 1;
      |                 ~~^~~
sequence.cpp: In member function 'int SegmentTree::qry(SegmentTree::node*&, int, int, int)':
sequence.cpp:87:19: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   87 |         int m = l + r >> 1;
      |                 ~~^~~
#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...