Submission #1107532

#TimeUsernameProblemLanguageResultExecution timeMemory
1107532qwerasdfzxclTortoise (CEOI21_tortoise)C++17
100 / 100
434 ms39632 KiB
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

constexpr int INF = 1e9 + 100;

int a[500500];

struct Seg {
    int tree[2002000], lazy[2002000];

    void init(int i, int l, int r, const vector<int> &V) {
        lazy[i] = 0;
        if (l==r) {tree[i] = V[l]; return;}
        int m = (l+r)/2;
        init(i<<1, l, m, V);
        init(i<<1|1, m+1, r, V);
        tree[i] = min(tree[i<<1], tree[i<<1|1]);
    }

    void propagate(int i, int l, int r) {
        tree[i] += lazy[i];
        if (l!=r) lazy[i<<1] += lazy[i], lazy[i<<1|1] += lazy[i];
        lazy[i] = 0;
    }

    void update(int i, int l, int r, int s, int e, int x) {
        propagate(i, l, r);
        if (r<s || e<l) return;
        if (s<=l && r<=e) {
            lazy[i] += x;
            propagate(i, l, r);
            return;
        }

        int m = (l+r)/2;
        update(i<<1, l, m, s, e, x);
        update(i<<1|1, m+1, r, s, e, x);
        tree[i] = min(tree[i<<1], tree[i<<1|1]);
    }

    void set(int i, int l, int r, int p, int x){
        propagate(i, l, r);
        if (r<p || p<l) return;
        if (l==r) {
            tree[i] = x;
            return;
        }

        int m = (l+r)/2;
        set(i<<1, l, m, p, x);
        set(i<<1|1, m+1, r, p, x);
        tree[i] = min(tree[i<<1], tree[i<<1|1]);
    }

    int query(int i, int l, int r, int s, int e) {
        propagate(i, l, r);
        if (r<s || e<l) return INF;
        if (s<=l && r<=e) return tree[i];

        int m = (l+r)/2;
        return min(query(i<<1, l, m, s, e), query(i<<1|1, m+1, r, s, e));
    }
}tree, tree2;

int main() {
    int n;
    scanf("%d", &n);

    for (int i=1;i<=n;i++) scanf("%d", a+i);
    a[0] = a[n+1] = -1;
    ll ans = 0;
    for (int i=1;i<=n;i++) ans += max(a[i], 0);

    if (ans==0) {
        printf("0\n");
        return 0;
    }

    priority_queue<array<int, 5>, vector<array<int, 5>>, greater<array<int, 5>>> pq;
    vector<int> V, W(n+1, INF), chk(n+1);
    vector<vector<int>> L;

    for (int i=0,j=0;i<=n;i=j) {
        if (a[i]!=-1){j = i+1; continue;}
        j = i+1;
        while(j <= n && a[j]!=-1) j++;

        int ti = i==0?-INF:i, tj = j==n+1?INF:j;

        int r = -1, mx = -1, idx = -1;
        for (int k=i+1;k<j;k++) if (a[k] > 0) {
            r = k;
            if (mx < min(k-ti, tj-k)) {
                mx = min(k-ti, tj-k);
                idx = k;
            }
        }
        if (r < 0) continue;

        V.push_back(-1);
        L.emplace_back();
        W[r] = r-1;
        chk[r] = 1;
        ans--;

        for (int k=i+1;k<j;k++) if (a[k] > 0){
            L.back().push_back(k);
            int c = k==idx?a[k]-1:a[k];
            if (c==0) continue;

            if (k-ti <= tj-k){
                pq.push({k-ti, c, k, (int)V.size()-1, 0});
            } 
            else{
                pq.push({tj-k, c, k, (int)V.size()-1, 1});
            } 
        }
    }

    int sz = V.size();
    tree.init(1, 0, n, W);
    tree2.init(1, 0, sz-1, V);

    while(!pq.empty()) {
        auto [w, c, x, i, typ] = pq.top(); pq.pop();

        if (typ==0 && !chk[x]){
            int v = tree2.query(1, 0, sz-1, i, i) + x;
            
            if (v < 0) continue;
            if (tree.query(1, 0, n, x+1, n) < w*2) continue;

            chk[x] = 1;
            tree.set(1, 0, n, x, v);
            tree.update(1, 0, n, x+1, n, -w*2);
            tree2.update(1, 0, sz-1, i, sz-1, -w*2);

            if (c > 1) pq.push({w, c-1, x, i, typ});
        }

        else if (typ==1 && c==1 && L[i].size() >= 2){
            int y = L[i].end()[-2];
            int v = tree2.query(1, 0, sz-1, i, i) + y;

            if (v < 0) continue;
            if (tree.query(1, 0, n, y+1, n) < w*2) continue;

            chk[y] = 1;
            tree.set(1, 0, n, y, v);
            tree.update(1, 0, n, y+1, n, -w*2);
            tree2.update(1, 0, sz-1, i+1, sz-1, -w*2);

            L[i].pop_back();
        }

        else{
            if (tree.query(1, 0, n, x, n) < w*2) continue;

            tree.update(1, 0, n, x, n, -w*2);
            tree2.update(1, 0, sz-1, i+typ, sz-1, -w*2);

            if (c > 1) pq.push({w, c-1, x, i, typ});
        }

        ans--;
    }

    printf("%lld\n", ans);
}

Compilation message (stderr)

tortoise.cpp: In function 'int main()':
tortoise.cpp:69:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   69 |     scanf("%d", &n);
      |     ~~~~~^~~~~~~~~~
tortoise.cpp:71:33: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   71 |     for (int i=1;i<=n;i++) scanf("%d", a+i);
      |                            ~~~~~^~~~~~~~~~~
#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...