Submission #425695

#TimeUsernameProblemLanguageResultExecution timeMemory
425695MlxaComparing Plants (IOI20_plants)C++14
100 / 100
1985 ms62312 KiB
#include <bits/stdc++.h> using namespace std; using ll = long long; #define all(x) x.begin(), x.end() #define mp make_pair #define mt make_tuple #define x first #define y second #include "plants.h" #define cerr if (0) cout namespace my { const int L = 18; const int N = 1 << L; int n, k, kth[N], can[N]; struct tree_t { pair<int, int> mi[2 * N]; int pu[2 * N]; int ls(int v) { return 2 * v + 1; } int rs(int v) { return 2 * v + 2; } void build(int v, int l, int r) { if (r - l == 1) { mi[v] = mp(kth[l], l); } else { int m = (l + r) / 2; build(ls(v), l, m); build(rs(v), m, r); mi[v] = min(mi[ls(v)], mi[rs(v)]); } } void build() { build(0, 0, N); } void push(int v) { mi[ls(v)].x += pu[v]; mi[rs(v)].x += pu[v]; pu[ls(v)] += pu[v]; pu[rs(v)] += pu[v]; pu[v] = 0; } void upd(int v, int vl, int vr, int ql, int qr, int d) { if (ql <= vl && vr <= qr) { mi[v].x += d; pu[v] += d; return; } if (qr <= vl || vr <= ql) { return; } push(v); int vm = (vl + vr) / 2; upd(ls(v), vl, vm, ql, qr, d); upd(rs(v), vm, vr, ql, qr, d); mi[v] = min(mi[ls(v)], mi[rs(v)]); } void range_add(int l, int r, int value) { upd(0, 0, N, l, r, value); } void cycle_add(int from, int value) { from %= n; from += n; from %= n; if (from + k <= n) { range_add(from, from + k, value); } else { range_add(from, n, value), range_add(0, from + k - n, value); } } pair<int, int> query(int v, int vl, int vr, int ql, int qr) { if (ql <= vl && vr <= qr) { return mi[v]; } if (qr <= vl || vr <= ql) { return mp(N, -1); } int vm = (vl + vr) / 2; push(v); return min(query(ls(v), vl, vm, ql, qr), query(rs(v), vm, vr, ql, qr)); } pair<int, int> range_min(int l, int r) { return query(0, 0, N, l, r); } pair<int, int> cycle_min(int from) { from %= n; from += n; from %= n; if (from + k <= n) { return range_min(from, from + k); } else { return min(range_min(from, n), range_min(0, from + k - n)); } } } tree; vector<int> topsort; void extract(int v) { tree.range_add(v, v + 1, N); while (1) { auto e = tree.cycle_min(v - k + 1); if (e.x) break; extract(e.y); } tree.cycle_add(v - k + 1, -1); topsort.push_back(v); } const int BAD = -1; int lef[L][N], rig[L][N]; } bool btw(int l, int r, int w) { if (l <= r) { return l <= w && w <= r; } else { return l <= w || w <= r; } } void init(int _k, vector<int> _r) { using namespace my; n = (int)_r.size(); k = _k; copy(all(_r), kth); tree.build(); while (1) { auto e = tree.range_min(0, n); if (e.x) break; extract(e.y); } assert((int)topsort.size() == n); reverse(all(topsort)); for (int i = 0; i < n; ++i) { can[topsort[i]] = i; } set<pair<int, int>> iset; for (int i = 0; i < k - 1; ++i) { iset.emplace(can[i], i); } fill_n(lef[0], L * N, BAD), fill_n(rig[0], L * N, BAD); for (int i = k - 1;;) { auto it = iset.lower_bound(mp(can[i], i)); if (it != iset.begin()) { --it; lef[0][i] = it->y; } iset.erase({can[(i + n - k + 1) % n], (i + n - k + 1) % n}); iset.emplace(can[i], i); (i += 1) %= n; if (i == k - 1) break; } iset.clear(); for (int i = 0; i < k - 1; ++i) { iset.emplace(can[i], i); } for (int i = n - 1; i >= 0; --i) { auto it = iset.lower_bound(mp(can[i], i)); if (it != iset.begin()) { --it; rig[0][i] = it->y; } iset.erase({can[(i + k - 1) % n], (i + k - 1) % n}); iset.emplace(can[i], i); } for (int i = 0; i < n; ++i) { cerr << i << " " << lef[0][i] << " " << rig[0][i] << endl; } for (int i = 0; i < n; ++i) { cerr << can[i] << " "; } cerr << endl; for (int it = 1; it < L; ++it) { for (int i = 0; i < n; ++i) { if (lef[it - 1][i] != BAD) { int j = lef[it - 1][i]; if (j == BAD || btw(lef[it - 1][j], j, i)) { continue; } lef[it][i] = lef[it - 1][j]; } } } for (int it = 1; it < L; ++it) { for (int i = 0; i < n; ++i) { if (rig[it - 1][i] != BAD) { int j = rig[it - 1][i]; if (j == BAD || btw(j, rig[it - 1][j], i)) { continue; } rig[it][i] = rig[it - 1][j]; } } } } bool taller(int x, int y) { using namespace my; cerr << "taller " << x << " " << y << endl; int z = x; for (int it = L - 1; it >= 0; --it) { int v = lef[it][z]; cerr << it << " " << z << " " << v << endl; if (v == BAD || btw(v, z, y)) { continue; } z = v; } cerr << "z = " << z << " " << y << endl; assert(lef[0][z] == BAD || btw(lef[0][z], z, y)); if (lef[0][z] != BAD && btw(lef[0][z], z, y) && can[z] >= can[y]) { return true; } z = x; for (int it = L - 1; it >= 0; --it) { int v = rig[it][z]; if (v == BAD || btw(z, v, y)) { continue; } z = v; } assert(rig[0][z] == BAD || btw(z, rig[0][z], y)); cerr << "z = " << z << endl; if (rig[0][z] != BAD && btw(z, rig[0][z], y) && can[z] >= can[y]) { return true; } return false; } int compare_plants(int x, int y) { if (taller(x, y)) { return 1; } else if (taller(y, x)) { return -1; } else { return 0; } } #ifdef LC #include "grader.cpp" #endif
#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...