Submission #848927

# Submission time Handle Problem Language Result Execution time Memory
848927 2023-09-13T17:55:47 Z mickey080929 Sushi (JOI16_sushi) C++17
15 / 100
5058 ms 97452 KB
#include <bits/stdc++.h>

#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")

#define sz(x) (int)(x).size()

using namespace std;

const int inf = 1e9;
const int B = 640;

struct LazySegmentTree{
    int tree[B*4+100];
    int lazy[B*4+100];
    void init(int n) {
        fill(tree, tree+n*4+10, inf);
        fill(lazy, lazy+n*4+10, 0);
    }
    void propagate(int node, int s, int e) {
        if (!lazy[node]) return;
        tree[node] += lazy[node];
        if (s != e) {
            lazy[node<<1] += lazy[node];
            lazy[node<<1|1] += lazy[node];
        }
        lazy[node] = 0;
    }
    void update_point(int node, int s, int e, int tar, int val) {
        propagate(node, s, e);
        if (s > tar || tar > e) return;
        if (s == e) {
            tree[node] = val;
            return;
        }
        int mid = s + e >> 1;
        update_point(node<<1, s, mid, tar, val);
        update_point(node<<1|1, mid+1, e, tar, val);
        tree[node] = min(tree[node<<1], tree[node<<1|1]);
    }
    void update_range(int node, int s, int e, int l, int r, int val) {
        propagate(node, s, e);
        if (l > e || s > r) return;
        if (l <= s && e <= r) {
            lazy[node] = val;
            propagate(node, s, e);
            return;
        }
        int mid = s + e >> 1;
        update_range(node<<1, s, mid, l, r, val);
        update_range(node<<1|1, mid+1, e, l, r, val);
        tree[node] = min(tree[node<<1], tree[node<<1|1]);
    }
    int getmin() { return tree[1]; }
};

struct Bucket{
    LazySegmentTree seg;
    priority_queue<int> pq;
    vector<int> queries;
    vector<int> a;
    vector<int> use;
    vector<int> nxt;
    void init() {
        while (!pq.empty()) pq.pop();
        use.clear();
        int cur = 0;
        for (int i=0; i<sz(a); i++) {
            pq.push(a[i]);
            if (cur <= a[i]) {
                cur = a[i];
                use.push_back(i);
            }
        }
        seg.init(sz(use));
        nxt.clear();
        nxt.resize(sz(use));
        cur = 0;
        for (int i=0; i<sz(use); i++) {
            int r = sz(a);
            if (i + 1 < sz(use)) r = use[i+1];
            if (use[i] + 1 >= r) {
                nxt[i] = cur;
                continue;
            }
            int idx = max_element(a.begin()+use[i]+1, a.begin()+r) - a.begin();
            if (cur >= a[idx]) {
                nxt[i] = cur;
                continue;
            }
            cur = a[idx];
            nxt[i] = cur;
            int lo = 0, hi = sz(use) - 1;
            while (lo < hi) {
                int mid = lo + hi >> 1;
                if (a[mid] <= cur) lo = mid + 1;
                else hi = mid;
            }
            seg.update_point(1, 1, sz(use), i+1, i+1 - lo);
        }
    }
    void apply() {
        vector<int> t;
        for (auto &x : queries) {
            int idx = lower_bound(nxt.begin(), nxt.end(), x) - nxt.begin();
            seg.update_range(1, 1, sz(use), idx+1, sz(use), -1);
            if (seg.getmin() <= 0) {
                for (auto &p : use) t.push_back(a[p]);
                sort(t.begin(), t.end());
                assert(sz(t) == sz(use));
                for (int i=0; i<sz(use); i++) a[use[i]] = t[i];
                t.clear();
                int cur = x;
                for (int i=0; i<sz(a); i++) if (cur <= a[i]) swap(cur, a[i]);
                init();
            } else t.push_back(x);
        }
        for (auto &p : use) t.push_back(a[p]);
        sort(t.begin(), t.end());
        for (int i=0; i<sz(use); i++) a[use[i]] = t[i];
        queries.clear();
        init();
    }
    int Push(int x) {
        queries.push_back(x);
        pq.push(x);
        int t = pq.top();
        pq.pop();
        return t;
    }
} buc[B];

int n, q;
int a[401010];

int query(int l, int r, int x) {
    int lb = l / B;
    int rb = r / B;
    buc[lb].apply();
    for (int i=l; i<=min({r, n-1, lb*B+B-1}); i++) {
        if (x < buc[lb].a[i-lb*B]) {
            swap(x, buc[lb].a[i-lb*B]);
        }
    }
    buc[lb].init();
    if (lb == rb) return x;
    for (int i=lb+1; i<=rb-1; i++) {
        x = buc[i].Push(x);
    }
    buc[rb].apply();
    for (int i=rb*B; i<=min(n-1, r); i++) {
        if (x < buc[rb].a[i-rb*B]) {
            swap(x, buc[rb].a[i-rb*B]);
        }
    }
    buc[rb].init();
    return x;
}

int main() {
    scanf("%d %d", &n, &q);
    for (int i=0; i<n; i++) {
        scanf("%d", &a[i]);
        buc[i/B].a.push_back(a[i]);
    }
    for (int i=0; i<=(n-1)/B; i++) {
        buc[i].init();
    }
    while (q --) {
        int l, r, x;
        scanf("%d %d %d", &l, &r, &x);
        l --; r --;
        if (l <= r) printf("%d\n", query(l, r, x));
        else printf("%d\n", query(0, r, query(l, n-1, x)));
    }

    return 0;
}

Compilation message

sushi.cpp: In member function 'void LazySegmentTree::update_point(int, int, int, int, int)':
sushi.cpp:37:21: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   37 |         int mid = s + e >> 1;
      |                   ~~^~~
sushi.cpp: In member function 'void LazySegmentTree::update_range(int, int, int, int, int, int)':
sushi.cpp:50:21: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   50 |         int mid = s + e >> 1;
      |                   ~~^~~
sushi.cpp: In member function 'void Bucket::init()':
sushi.cpp:96:30: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   96 |                 int mid = lo + hi >> 1;
      |                           ~~~^~~~
sushi.cpp: In function 'int main()':
sushi.cpp:162:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  162 |     scanf("%d %d", &n, &q);
      |     ~~~~~^~~~~~~~~~~~~~~~~
sushi.cpp:164:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  164 |         scanf("%d", &a[i]);
      |         ~~~~~^~~~~~~~~~~~~
sushi.cpp:172:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  172 |         scanf("%d %d %d", &l, &r, &x);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
# Verdict Execution time Memory Grader output
1 Correct 342 ms 14928 KB Output is correct
2 Correct 338 ms 14932 KB Output is correct
3 Runtime error 271 ms 29924 KB Execution killed with signal 6
4 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 4766 ms 92028 KB Output is correct
2 Correct 4966 ms 92108 KB Output is correct
3 Correct 2345 ms 94164 KB Output is correct
4 Correct 4732 ms 92176 KB Output is correct
5 Correct 3207 ms 96836 KB Output is correct
6 Correct 5058 ms 94560 KB Output is correct
7 Correct 5053 ms 94600 KB Output is correct
8 Correct 4764 ms 96948 KB Output is correct
9 Correct 2013 ms 96760 KB Output is correct
10 Correct 3477 ms 97452 KB Output is correct
11 Correct 1964 ms 96868 KB Output is correct
12 Correct 3418 ms 97016 KB Output is correct
13 Correct 4610 ms 92164 KB Output is correct
14 Correct 4802 ms 91980 KB Output is correct
15 Correct 2104 ms 94228 KB Output is correct
16 Correct 4674 ms 92132 KB Output is correct
17 Correct 3054 ms 97016 KB Output is correct
18 Correct 4861 ms 94580 KB Output is correct
19 Correct 4847 ms 94572 KB Output is correct
20 Correct 4753 ms 97004 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 342 ms 14928 KB Output is correct
2 Correct 338 ms 14932 KB Output is correct
3 Runtime error 271 ms 29924 KB Execution killed with signal 6
4 Halted 0 ms 0 KB -