Submission #569514

#TimeUsernameProblemLanguageResultExecution timeMemory
569514hoanghq2004Comparing Plants (IOI20_plants)C++14
100 / 100
958 ms56092 KiB
#include <bits/stdc++.h>
#pragma GCC optimize ("O3")
#pragma GCC optimize ("unroll-loops")
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include "plants.h"
using namespace __gnu_pbds;
using namespace std;

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

const int N = 2e5 + 10;

int n;
int p[N];
int lft[N][20], rgt[N][20];

struct node {
    int minval;
    int maxid, minid;
    int lazy;
    node() {
        minval = 1e9;
        maxid = minid = -1;
    }
    node operator + (const node& other) const {
        node ret;
        if (minval < other.minval) {
            ret = *this;
            ret.lazy = 0;
        } else if (minval > other.minval) {
            ret = other;
            ret.lazy = 0;
        } else {
            ret.minval = minval;
            ret.maxid = other.maxid;
            ret.minid = minid;
            ret.lazy = 0;
        }
        return ret;
    }
} st[N * 4];


void push(int id, int delta) {
    st[id].lazy += delta;
    st[id].minval += delta;
}

void update(int id, int L, int R, int i, int val) {
    if (L == R) {
        st[id].minval = val;
        st[id].maxid = st[id].minid = L;
        return;
    }
    int mid = L + R >> 1;
    push(id * 2, st[id].lazy);
    push(id * 2 + 1, st[id].lazy);
    st[id].lazy = 0;
    if (i <= mid) update(id * 2, L, mid, i, val);
    else update(id * 2 + 1, mid + 1, R, i, val);
    st[id] = st[id * 2] + st[id * 2 + 1];
}

void add(int id, int L, int R, int u, int v, int delta) {
    if (u > R || L > v) return;
    if (u <= L && R <= v) {
        push(id, delta);
        return;
    }
    int mid = L + R >> 1;
    push(id * 2, st[id].lazy);
    push(id * 2 + 1, st[id].lazy);
    st[id].lazy = 0;
    add(id * 2, L, mid, u, v, delta);
    add(id * 2 + 1, mid + 1, R, u, v, delta);
    st[id] = st[id * 2] + st[id * 2 + 1];
}

node get(int id, int L, int R, int u, int v) {
    if (u > R || L > v) return node();
    if (u <= L && R <= v) return st[id];
    int mid = L + R >> 1;
    push(id * 2, st[id].lazy);
    push(id * 2 + 1, st[id].lazy);
    st[id].lazy = 0;
    return get(id * 2, L, mid, u, v) + get(id * 2 + 1, mid + 1, R, u, v);
}

int dist(int x, int y) {
    return (y - x + n) % n;
}

void init(int k, vector<int> r) {
    n = r.size();
    for (int i = 0; i < n; ++i) update(1, 0, n - 1, i, r[i]);

    auto check = [&](int i) {
        if (get(1, 0, n - 1, i, i).minval > 0) return 0;
        if (i - k + 1 < 0) {
            if (get(1, 0, n - 1, 0, i - 1).minval <= 0) return 0;
            if (get(1, 0, n - 1, (i - k + 1 + n) % n, n - 1).minval <= 0) return 0;
            return 1;
        } else {
            if (get(1, 0, n - 1, i - k + 1, i - 1).minval <= 0) return 0;
            return 1;
        }
    };
    auto get_next = [&](int u) {
        if (st[1].minval > 0) return -1;
        node cur = get(1, 0, n - 1, u, n - 1);
        if (cur.minval <= 0) return cur.minid;
        cur = get(1, 0, n - 1, 0, u - 1);
        if (cur.minval <= 0) return cur.minid;
        return -1;
    };
    auto get_prev = [&](int u) {
        if (st[1].minval > 0) return -1;
        node cur = get(1, 0, n - 1, 0, u - 1);
        if (cur.minval <= 0) return cur.maxid;
        cur = get(1, 0, n - 1, u, n - 1);
        if (cur.minval <= 0) return cur.maxid;
        return -1;
    };
    int m = n;
    auto add_range = [&](int i, int k) {
        if (i - k + 1 < 0) {
            if (i != 0) add(1, 0, n - 1, 0, i - 1, -1);
            add(1, 0, n - 1, (i - k + 1 + n) % n, n - 1, -1);
        } else {
            add(1, 0, n - 1, i - k + 1, i - 1, -1);
        }
    };
    function <void(int)> dfs = [&](int u) {
        while (1) {
            int v = get_prev(u);
            if (v != u && dist(v, u) + 1 <= k) {
                dfs(v);
            }
            else break;
        }
        p[u] = --m;
        add_range(u, k);
        update(1, 0, n - 1, u, 1e9);
    };
    while (st[1].minval <= 0) {
        int i = st[1].minid;
        dfs(i);
    }
    for (int i = 0; i < N * 4; ++i) st[i] = node();
    vector <int> s(n);
    for (int i = 0; i < n; ++i) s[p[i]] = i;
    for (int id = 0; id < n; ++id) {
        int i = s[id];
        if (i - k + 1 >= 0) {
            lft[i][0] = get(1, 0, n - 1, i - k + 1, i - 1).minid;
        } else {
            lft[i][0] = (get(1, 0, n - 1, 0, i - 1) + get(1, 0, n - 1, (i - k + 1 + n) % n, n - 1)).minid;
        }
        if (i + k - 1 < n) {
            rgt[i][0] = get(1, 0, n - 1, i + 1, i + k - 1).minid;
        } else {
            rgt[i][0] = (get(1, 0, n - 1, i + 1, n - 1) + get(1, 0, n - 1, 0, (i + k - 1) % n)).minid;
        }
        update(1, 0, n - 1, i, - p[i]);
    }
    for (int i = 0; i < n; ++i) {
        if (lft[i][0] == -1) lft[i][0] = i;
        if (rgt[i][0] == -1) rgt[i][0] = i;
        lft[i][0] = dist(lft[i][0], i);
        rgt[i][0] = dist(i, rgt[i][0]);
    }

    for (int lg = 1; lg < 20; ++lg) {
        for (int i = 0; i < n; ++i) {
            lft[i][lg] = min(lft[i][lg - 1] + lft[(i - lft[i][lg - 1] % n + n) % n][lg - 1], n);
            rgt[i][lg] = min(rgt[i][lg - 1] + rgt[(i + rgt[i][lg - 1]) % n][lg - 1], n);
        }
    }
}


int reachable(int x, int y) {
    int w = x;
    for (int i = 19; i >= 0; --i)
        if (dist(w, x) + lft[w][i] < dist(y, x)) {
            w = (w - lft[w][i] % n + n) % n;
        }

    if (lft[w][0] && p[w] > p[y]) return 1;
    w = x;
    for (int i = 19; i >= 0; --i)
        if (dist(x, w) + rgt[w][i] < dist(x, y)) {
            w = (w + rgt[w][i]) % n;
        }
    if (rgt[w][0] && p[w] > p[y]) return 1;
    return 0;
}


int compare_plants(int x, int y) {
    if (reachable(x, y)) return 1;
    if (reachable(y, x)) return -1;
    return 0;
}

Compilation message (stderr)

plants.cpp: In function 'void update(int, int, int, int, int)':
plants.cpp:57:17: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   57 |     int mid = L + R >> 1;
      |               ~~^~~
plants.cpp: In function 'void add(int, int, int, int, int, int)':
plants.cpp:72:17: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   72 |     int mid = L + R >> 1;
      |               ~~^~~
plants.cpp: In function 'node get(int, int, int, int, int)':
plants.cpp:84:17: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   84 |     int mid = L + R >> 1;
      |               ~~^~~
plants.cpp: In function 'void init(int, std::vector<int>)':
plants.cpp:99:10: warning: variable 'check' set but not used [-Wunused-but-set-variable]
   99 |     auto check = [&](int i) {
      |          ^~~~~
plants.cpp:110:10: warning: variable 'get_next' set but not used [-Wunused-but-set-variable]
  110 |     auto get_next = [&](int u) {
      |          ^~~~~~~~
#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...