Submission #1259321

#TimeUsernameProblemLanguageResultExecution timeMemory
1259321biankComparing Plants (IOI20_plants)C++20
100 / 100
1216 ms140068 KiB
#include "plants.h" #include <bits/stdc++.h> #define forsn(i, s, n) for (int i = int(s); i < int(n); i++) #define forn(i, n) forsn(i, 0, n) #define dforsn(i, s, n) for (int i = int(n) - 1; i >= int(s); i--) #define dforn(i, n) dforsn(i, 0, n) #define sz(x) int(x.size()) #define all(x) begin(x), end(x) #define pb push_back #define eb emplace_back #define fst first #define snd second using namespace std; using vi = vector<int>; using ii = pair<int, int>; using ll = long long; const int INF = 1e9, SZ = 1 << 19; ii operator+(const ii &a, const int b) { return {a.fst + b, a.snd}; } struct Node { ii l, ans; int tam, mini, r; Node() { ans = ii{-INF, -1}, l = ii{0, -1}, tam = r = 0, mini = INF; } Node(const int &val, const int &idx) { ans = l = {1, idx}, tam = 1, mini = val, r = 0; } friend Node merge(const Node &a, const Node &b) { Node c; c.tam = a.tam + b.tam; c.mini = min(a.mini, b.mini); c.l = a.l, c.r = b.r; if (a.mini == b.mini) { c.ans = max({a.ans, b.ans, b.l+a.r}); } else if (a.mini < b.mini) { c.r = a.r + b.tam; c.ans = a.ans; } else { c.l = b.l + a.tam; c.ans = max(c.l, b.ans); } return c; } }; Node st[2 * SZ]; int lazy[2 * SZ]; void pass(int u) { if (u < SZ) { lazy[2 * u] += lazy[u]; lazy[2 * u + 1] += lazy[u]; } st[u].mini += lazy[u]; lazy[u] = 0; } void update(int s, int e, int v, int l = 0, int r = SZ, int u = 1) { pass(u); if (e <= l || r <= s) return; if (s <= l && r <= e) { lazy[u] = v; return pass(u); } int m = (l + r) / 2; update(s, e, v, l, m, 2 * u); update(s, e, v, m, r, 2 * u + 1); st[u] = merge(st[2 * u], st[2 * u + 1]); } const int MAX_N = 2e5 + 9; const int MAX_K = 20; int L[MAX_K][MAX_N], R[MAX_K][MAX_N]; ll distL[MAX_K][MAX_N], distR[MAX_K][MAX_N]; int N, K, h[MAX_N]; ii maxi[2 * SZ]; void updateMaxi(int p, int v) { maxi[p += SZ].fst = v; while (p /= 2) maxi[p] = max(maxi[2 * p], maxi[2 * p + 1]); } void chmax(ii &a, ii b) { if (b > a) a = b; } ii queryMaxi(int l, int r) { ii ret = {-INF, -1}; for (l += SZ, r += SZ; l < r; l /= 2, r /= 2) { if (l & 1) chmax(ret, maxi[l++]); if (r & 1) chmax(ret, maxi[--r]); } return ret; } void init(int k, vector <int> r) { const int n = sz(r); N = n, K = k; forn(i, 2 * n) st[i + SZ] = Node(r[i % n], i); dforsn(i, 1, SZ) st[i] = merge(st[2 * i], st[2 * i + 1]); vi order; forn(i, n) { auto [_, pos] = st[1].ans; pos %= n; order.pb(pos); if (k <= pos) { update(pos - k + 1, pos, -1); } else { update(0, pos, -1); update(2 * n + pos - k + 1, 2 * n, -1); } update(pos - k + 1 + n, pos + n, -1); update(pos, pos + 1, INF); update(pos + n, pos + n + 1, INF); h[pos] = n - i - 1; } reverse(all(order)); forn(i, 2 * SZ) maxi[i] = {-INF, i - SZ}; for (int pos : order) { ii bestLeft = {-INF, -1}, bestRight = {-INF, -1}; if (k <= pos) { chmax(bestLeft, queryMaxi(pos - k + 1, pos)); } else { chmax(bestLeft, queryMaxi(0, pos)); chmax(bestLeft, queryMaxi(n + pos - k + 1, 2 * n)); } if (pos < n - k + 1) { chmax(bestRight, queryMaxi(pos + 1, pos + k)); } else { chmax(bestRight, queryMaxi(pos + 1, n)); chmax(bestRight, queryMaxi(0, pos + k - n)); } if (bestLeft.fst == -INF) bestLeft.snd = pos; if (bestRight.fst == -INF) bestRight.snd = pos; L[0][pos] = bestLeft.snd; distL[0][pos] = (pos - L[0][pos] + n) % n; R[0][pos] = bestRight.snd; distR[0][pos] = (R[0][pos] - pos + n) % n; updateMaxi(pos, h[pos]); } forn(p, MAX_K - 1) forn(i, n) { int j = L[p][i]; L[p + 1][i] = L[p][j]; distL[p + 1][i] = distL[p][i] + distL[p][j]; } forn(p, MAX_K - 1) forn(i, n) { int j = R[p][i]; R[p + 1][i] = R[p][j]; distR[p + 1][i] = distR[p][i] + distR[p][j]; } } bool reacheableLeft(int x, int y) { ll currDist = (x - y + N) % N; dforn(i, MAX_K) { if (currDist >= distL[i][x]) { currDist -= distL[i][x]; x = L[i][x]; } } return currDist < K && h[x] >= h[y]; } bool reacheableRight(int x, int y) { ll currDist = (y - x + N) % N; dforn(i, MAX_K) { if (currDist >= distR[i][x]) { currDist -= distR[i][x]; x = R[i][x]; } } return currDist < K && h[x] >= h[y]; } bool reacheable(int x, int y) { return reacheableLeft(x, y) || reacheableRight(x, y); } int compare_plants(int x, int y) { if (reacheable(x, y)) return 1; if (reacheable(y, x)) return -1; return 0; }
#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...