Submission #790822

#TimeUsernameProblemLanguageResultExecution timeMemory
790822restingComparing Plants (IOI20_plants)C++17
100 / 100
1201 ms115940 KiB
#include "plants.h" #include <bits/stdc++.h> using namespace std; #define time fuck const int mx = 2e5 + 5; int n, k; struct segtree { int l, r, lz = 0, mn = 0; segtree* lc = 0, * rc = 0; segtree* getmem(); segtree() : segtree(-1, -1) {}; segtree(int l, int r) : l(l), r(r) { if (l == r)return; int m = (l + r) / 2; lc = getmem(); *lc = segtree(l, m); rc = getmem(); *rc = segtree(m + 1, r); } void apply(int v) { mn += v; lz += v; } void push() { if (l == r) return; lc->apply(lz);rc->apply(lz); lz = 0; } void pull() { if (l == r) return; mn = min(lc->mn, rc->mn); } void upd(int ql, int qr, int qv) { if (qr < 0) { ql += n; qr += n; } if (ql < 0) { upd(0, qr, qv); upd((n)+ql, (n - 1), qv); return; } if (ql >= n) { ql -= n; qr -= n; } if (qr >= n) { upd(ql, (n - 1), qv); upd(0, qr - (n), qv); return; } if (l > qr || r < ql) return; if (ql <= l && r <= qr) { apply(qv); return; } push(); lc->upd(ql, qr, qv); rc->upd(ql, qr, qv); pull(); } int extract_min() { if (l == r) return l; push(); if (lc->mn == mn) return lc->extract_min(); return rc->extract_min(); } }mem[mx * 8]; int memsz = 0; segtree* segtree::getmem() { return &mem[memsz++]; } const int inf = 1e9 + 7; namespace rmq { struct segtree { int l, r; segtree* lc = 0, * rc = 0; pair<int, int> v = { -1, -1 }; segtree* getmem(); segtree() : segtree(-1, -1) {}; segtree(int l, int r) : l(l), r(r) { if (l == r)return; int m = (l + r) / 2; lc = getmem(); *lc = segtree(l, m); rc = getmem(); *rc = segtree(m + 1, r); } void upd(int qi, int qv) { if (l == r) { v = { qv, qi };return; } if (qi <= lc->r) lc->upd(qi, qv); else rc->upd(qi, qv); v = max(lc->v, rc->v); } pair<int, int> q(int ql, int qr) { if (qr < 0) { ql += n; qr += n; } if (ql < 0) { return max(q(0, qr), q((n)+ql, (n - 1))); } if (ql >= n) { ql -= n; qr -= n; } if (qr >= n) { return max(q(ql, (n - 1)), q(0, qr - (n))); } if (l > qr || r < ql)return { -1, -1 }; if (ql <= l && r <= qr) return v; return max(lc->q(ql, qr), rc->q(ql, qr)); } }mem[mx * 4]; int memsz = 0; segtree* segtree::getmem() { return &mem[memsz++]; } } vector<int> time, rtime; int parl[mx][20], parr[mx][20]; int cheat[500][500]{}; void init(int kk, std::vector<int> r) { n = r.size();k = kk;k--; time = rtime = vector<int>(n, 0); segtree parta(0, n - 1), partb(0, n - 1); partb.upd(0, n - 1, 1); for (int i = 0; i < n; i++) parta.upd(i, i, r[i]); for (int i = 0; i < n; i++) { while (parta.mn == 0) { int t = parta.extract_min(); parta.upd(t, t, mx); partb.upd(t, t, -1); partb.upd(t + 1, t + k, 1); } int t = partb.extract_min(); time[t] = i; rtime[i] = t; partb.upd(t, t, mx); partb.upd(t + 1, t + k, -1); parta.upd(t - k, t, -1); } rmq::segtree tim(0, n - 1); for (int i = 0; i < n; i++) { int t = tim.q(rtime[i] - k, rtime[i]).second; if (t == -1) parl[rtime[i]][0] = rtime[i]; else parl[rtime[i]][0] = t; // cout << "#" << t << endl; t = tim.q(rtime[i], rtime[i] + k).second; // cout << "#" << t << endl; if (t == -1) parr[rtime[i]][0] = rtime[i]; else parr[rtime[i]][0] = t; tim.upd(rtime[i], i); } for (int i = 1; i < 20; i++) { for (int j = 0; j < n; j++) { if (parl[j][0] > j) parl[j][i] = parl[j][i - 1]; else if (parl[parl[j][i - 1]][0] > parl[j][i - 1]) parl[j][i] = parl[j][i - 1]; else parl[j][i] = parl[parl[j][i - 1]][i - 1]; } } for (int i = 1; i < 20; i++) { for (int j = 0; j < n; j++) { if (parr[j][0] < j) parr[j][i] = parr[j][i - 1]; else if (parr[parr[j][i - 1]][0] < parr[j][i - 1]) parr[j][i] = parr[j][i - 1]; else parr[j][i] = parr[parr[j][i - 1]][i - 1]; } } if (n <= 300) { for (int i = 0; i < n; i++) { for (int j = 1; j <= k; j++) { int j2 = (i + j) % n; if (time[j2] < time[i]) cheat[i][j2] = 1; else cheat[j2][i] = 1; } } for (int i = 0; i < n; i++) { for (int x = 0; x < n; x++) { for (int y = 0; y < n; y++) { cheat[x][y] |= cheat[x][i] && cheat[i][y]; } } } } for (int i = 0; i < n; i++) for (int j = 1; j < 20; j++) assert(parr[i][j] >= parr[i][j - 1] && (time[parr[i][j]] <= time[parr[i][j - 1]])); for (int i = 0; i < n; i++) for (int j = 1; j < 20; j++) assert(parl[i][j] <= parl[i][j - 1] && (time[parl[i][j]] <= time[parl[i][j - 1]])); return; } int compare_plants(int x, int y) { // if (n <= 300) { // if (cheat[x][y]) return -1; // if (cheat[y][x])return 1; // return 0; // } //compare zero if (x + k >= y || y + k - n >= x) { return time[x] < time[y] ? 1 : -1; } // if (n <= 300) { // //brute force // //compare one // int t = x; // for (int i = n; i >= 0; i--) { // if (parr[t][0] + k < y) t = parr[t][0]; // } // t = parr[t][0]; // if (t + k >= y && time[t] > time[y]) return -1; // //compare two // t = x;; // while (parl[t][0] != t && parl[t][0] < t) t = parl[t][0]; // if (y + k - n >= t && time[t] > time[y]) return -1; // if (t != parl[t][0]) { // t = parl[t][0]; // for (int i = n; i >= 0; i--) { // if (y + k < parl[t][0]) t = parl[t][0]; // } // t = parl[t][0]; // if (y + k >= t && time[t] > time[y])return -1; // } // //compare three // t = y; // for (int i = n; i >= 0; i--) { // if (x + k < parl[t][0]) t = parl[t][0]; // } // t = parl[t][0]; // if (x + k >= t && time[t] > time[x]) return 1; // //compare four // t = y; // while (parr[t][0] != t && parr[t][0] > t) t = parr[t][0]; // if (t + k - n >= x && time[t] > time[x]) return 1; // if (t != parr[t][0]) { // t = parr[t][0]; // for (int i = n; i >= 0; i--) { // if (parr[t][0] + k < x) t = parr[t][0]; // } // t = parr[t][0]; // if (t + k >= x && time[t] > time[x]) return 1; // } // } //compare one int t = x; for (int i = 19; i >= 0; i--) { //assert(parr[t][i] >= t); if (parr[t][i] + k < y) t = parr[t][i]; } t = parr[t][0]; if (t + k >= y && time[t] >= time[y]) return -1; //compare two t = x; for (int i = 19; i >= 0; i--) if (parl[t][i] < t && time[parl[t][i]] >= time[y]) t = parl[t][i]; if (y + k - n >= t && time[t] >= time[y]) return -1; if (t != parl[t][0]) { t = parl[t][0]; for (int i = 19; i >= 0; i--) { if (y + k < parl[t][i]) t = parl[t][i]; } t = parl[t][0]; if (y + k >= t && time[t] >= time[y])return -1; } //compare three t = y; for (int i = 19; i >= 0; i--) { // assert(parl[t][i] <= t); if (x + k < parl[t][i]) t = parl[t][i]; } t = parl[t][0]; if (x + k >= t && time[t] >= time[x]) return 1; //compare four t = y; for (int i = 19; i >= 0; i--) { if (parr[t][i] > t && time[parr[t][i]] >= time[x]) t = parr[t][i]; } if (t + k - n >= x && time[t] >= time[x]) return 1; if (t != parr[t][0]) { t = parr[t][0]; if (t + k >= x && time[t] >= time[x]) return 1; for (int i = 19; i >= 0; i--) { if (parr[t][i] + k < x) t = parr[t][i]; } t = parr[t][0]; if (t + k >= x && time[t] >= time[x]) return 1; } return 0; } // int main() { // init(3, { 0, 1, 1, 2 }); // cout << compare_plants(0, 2) << endl; // cout << compare_plants(1, 2) << endl; // }
#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...