Submission #405413

#TimeUsernameProblemLanguageResultExecution timeMemory
405413tiberiuComparing Plants (IOI20_plants)C++14
0 / 100
4098 ms460 KiB
#include "plants.h" #include <iostream> using namespace std; const int MAX_N = 2e5; int N, K; int v[MAX_N], hGen[MAX_N]; int aint_mn[4 * MAX_N]; int aint_pos[4 * MAX_N]; int aint_lazy[4 * MAX_N]; int cval; void propag(int n, int nl, int nr) { aint_mn[n * 2 + 1] += aint_lazy[n]; aint_lazy[n * 2 + 1] += aint_lazy[n]; aint_mn[n * 2 + 2] += aint_lazy[n]; aint_lazy[n * 2 + 2] += aint_lazy[n]; aint_lazy[n] = 0; } void init_aint(int n = 0, int nl = 0, int nr = 0) { if (n == 0) nr = N - 1; aint_pos[n] = nl; if (nl < nr) { int mid = (nl + nr) / 2; init_aint(n * 2 + 1, nl, mid); init_aint(n * 2 + 2, mid + 1, nr); } } pair<int, int> query(int l, int r, int n = 0, int nl = 0, int nr = 0) { if (n == 0) nr = N - 1; if (l == nl && r == nr) { return {aint_mn[n], aint_pos[n]}; } propag(n, nl, nr); pair<int, int> q1, q2; int mid = (nl + nr) / 2; if (r <= mid) return query(l, r, n * 2 + 1, nl, mid); else if (l > mid) return query(l, r, n * 2 + 2, mid + 1, nr); else { q1 = query(l, mid, n * 2 + 1, nl, mid); q2 = query(mid + 1, r, n * 2 + 2, mid + 1, nr); return min(q1, q2); } } void update(int l, int r, int val, int n = 0, int nl = 0, int nr = 0) { if (n == 0) nr = N - 1; if (l == nl && r == nr) { aint_mn[n] += val; aint_lazy[n] += val; return; } propag(n, nl, nr); int mid = (nl + nr) / 2; if (l <= mid) update(l, min(mid, r), val, n * 2 + 1, nl, mid); if (r > mid) update(max(mid + 1, l), r, val, n * 2 + 2, mid + 1, nr); if (aint_mn[n * 2 + 1] < aint_mn[n * 2 + 2]) { aint_mn[n] = aint_mn[n * 2 + 1]; aint_pos[n] = aint_pos[n * 2 + 1]; } else { aint_mn[n] = aint_mn[n * 2 + 2]; aint_pos[n] = aint_pos[n * 2 + 2]; } } void solve(int x) { if (x >= K - 1) { pair<int, int> q = query(x - K + 1, x - 1); if (q.first == 0) { solve(q.second); solve(x); return; } } else { pair<int, int> q = query(N + x - K + 1, N - 1); if (q.first != 0 && x > 0) q = query(0, x - 1); if (q.first == 0) { solve(q.second); solve(x); return; } } hGen[x] = cval; cval--; if (x >= K - 1) { update(x - K + 1, x - 1, -1); } else { if (x > 0) update(0, x - 1, -1); update(N + x - K + 1, N - 1, -1); } update(x, x, +1000000); } void gen(int k, vector<int> r) { init_aint(); for (int i = 0; i < N; i++) { update(i, i, r[i]); } cval = N; while (aint_mn[0] == 0) { solve(aint_pos[0]); } } const int LOG = 20; int leftV[LOG][MAX_N]; int rightV[LOG][MAX_N]; #include <set> void calc_lr() { multiset<pair<int, int>> w; for (int i = N - K + 1; i < N; i++) { w.insert({hGen[i], i}); } for (int i = 0; i < N; i++) { multiset<pair<int, int>>::iterator it = w.lower_bound({hGen[i], i}); if (it != w.begin()) { it--; leftV[0][i] = (i - it->second + N) % N; } int rmv = (N + i - K + 1) % N; w.erase({hGen[rmv], rmv}); w.insert({hGen[i], i}); } w.clear(); for (int i = 0; i < K - 1; i++) { w.insert({hGen[i], i}); } for (int i = N - 1; i >= 0; i--) { multiset<pair<int, int>>::iterator it = w.lower_bound({hGen[i], i}); if (it != w.begin()) { it--; rightV[0][i] = (it->second - i + N) % N; } int rmv = (N + i + K - 1) % N; w.erase({hGen[rmv], rmv}); w.insert({hGen[i], i}); } for (int l = 1; l < LOG; l++) for (int i = 0; i < N; i++) { rightV[l][i] = rightV[l - 1][i] + rightV[l - 1][(i + rightV[l - 1][i]) % N]; leftV[l][i] = leftV[l - 1][i] + leftV[l - 1][(i - rightV[l - 1][i] % N + N) % N]; } } void init(int k, std::vector<int> r) { K = k; N = r.size(); gen(k, r); calc_lr(); return; } int dist(int a, int b) { return (b - a + N) % N; } int move_right(int pos, int bound) { for (int l = LOG - 1; l >= 0; l--) while (rightV[l][pos] < dist(pos, bound)) pos = (pos + rightV[l][pos]) % N; return pos; } int move_left(int pos, int bound) { for (int l = LOG - 1; l >= 0; l--) while (leftV[l][pos] < dist(bound, pos)) pos = (pos - leftV[l][pos] + N) % N; return pos; } int compare_plants(int x0, int y0) { int x = x0, y = y0; x = move_right(x0, y0); if (dist(x, y0) < K && hGen[x] > hGen[y0]) return 1; y = move_left(y0, x0); if (dist(x0, y) < K && hGen[y] > hGen[x0]) return -1; x = move_left(x0, y0); if (dist(y0, x) < K && hGen[x] > hGen[y0]) return 1; y = move_right(y0, x0); if (dist(y, x0) < K && hGen[y] > hGen[x0]) 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...