Submission #444172

#TimeUsernameProblemLanguageResultExecution timeMemory
444172peijarComparing Plants (IOI20_plants)C++17
59 / 100
1008 ms32672 KiB
#include "plants.h" #include <bits/stdc++.h> #include <type_traits> using namespace std; /* * Si h[i] < h[i+1], alors r[i+1] <= r[i] * Si h[i] > h[i+1] alors r[i+1] >= r[i] * Donc si on a r[i] != r[i+1] on peut comparer r[i] et r[i+1] ! * r[i+1] > r[i] => h[i+1] < h[i] * r[i+1] < r[i] => h[i+1] > h[i] * 1 : AC * 2 : AC * 3 : AC * 4 : AC * 5 : AC * 6 : AC * 7 : NA * * If can build graph efficiently then ez ! */ const int MAXN = 2e5; int k; int nbPlusGrands[MAXN], cntEq[MAXN][2]; vector<int> adj[MAXN]; int ordre[MAXN]; int nbDevant[MAXN]; bool reach[301][301]; vector<int> orderLarge, orderSmall; int nbPlantes; struct Seg { int nbValeurs; vector<int> order; vector<int> valeurs; vector<int> iDeb, iFin, lazy, minVal; const int INF = 1e9; Seg(vector<int> _v) : nbValeurs(_v.size()), valeurs(_v) { int p = 0; while ((1 << p) < nbValeurs) ++p; int x = 2 * (1 << p) + 1; iDeb.resize(x), iFin.resize(x), lazy.resize(x), minVal.resize(x); buildTree(1, 0, nbValeurs - 1); while ((int)order.size() < nbValeurs) getNxt(); } void pull(int iNoeud) { minVal[iNoeud] = min(minVal[2 * iNoeud], minVal[2 * iNoeud + 1]); } void push(int iNoeud) { if (!lazy[iNoeud]) return; minVal[iNoeud] += lazy[iNoeud]; if (iDeb[iNoeud] < iFin[iNoeud]) { lazy[2 * iNoeud] += lazy[iNoeud]; lazy[2 * iNoeud + 1] += lazy[iNoeud]; } lazy[iNoeud] = 0; } void buildTree(int iNoeud, int deb, int fin) { iDeb[iNoeud] = deb, iFin[iNoeud] = fin; if (deb == fin) { minVal[iNoeud] = valeurs[deb]; return; } buildTree(2 * iNoeud, deb, (deb + fin) / 2); buildTree(2 * iNoeud + 1, (deb + fin) / 2 + 1, fin); pull(iNoeud); } int queryMin(int iNoeud, int deb, int fin) { push(iNoeud); if (deb > iFin[iNoeud] or fin < iDeb[iNoeud]) return 2 * INF; if (iDeb[iNoeud] >= deb and iFin[iNoeud] <= fin) return minVal[iNoeud]; return min(queryMin(2 * iNoeud, deb, fin), queryMin(2 * iNoeud + 1, deb, fin)); } void decrement(int iNoeud, int deb, int fin) { push(iNoeud); if (deb > iFin[iNoeud] or fin < iDeb[iNoeud]) return; if (deb <= iDeb[iNoeud] and iFin[iNoeud] <= fin) { lazy[iNoeud]--; push(iNoeud); return; } decrement(2 * iNoeud, deb, fin); decrement(1 + 2 * iNoeud, deb, fin); pull(iNoeud); } int findFirstZero(int iNoeud, int deb, int fin) { push(iNoeud); if (minVal[iNoeud] or iDeb[iNoeud] > fin or iFin[iNoeud] < deb) return -1; if (iDeb[iNoeud] == iFin[iNoeud]) return iDeb[iNoeud]; int retLft = findFirstZero(2 * iNoeud, deb, fin); if (retLft != -1) return retLft; return findFirstZero(2 * iNoeud + 1, deb, fin); } void delVal(int iNoeud, int pos) { push(iNoeud); if (iDeb[iNoeud] > pos or iFin[iNoeud] < pos) return; if (iDeb[iNoeud] == iFin[iNoeud]) { minVal[iNoeud] = INF; return; } delVal(2 * iNoeud, pos); delVal(2 * iNoeud + 1, pos); pull(iNoeud); } int findZeroBefore(int pos) { int posAvant = pos - k + 1; if (posAvant >= 0) return findFirstZero(1, posAvant, pos - 1); else { posAvant += nbValeurs; int ret = findFirstZero(1, posAvant, nbValeurs - 1); if (ret == -1 and pos) ret = findFirstZero(1, 0, pos - 1); return ret; } } void get(int pos) { // cout << "EXTRACTING " << pos << endl; while (true) { int x = findZeroBefore(pos); if (x == -1) break; get(x); } order.push_back(pos); int posAvant = pos - k + 1; delVal(1, pos); if (pos) decrement(1, max(0, posAvant), pos - 1); if (posAvant < 0) decrement(1, posAvant + nbValeurs, nbValeurs - 1); // cout << "EXTRACTED " << pos << endl; } void getNxt() { /*cout << "FINDING NEXT : " << endl; for (int i = 0; i < nbValeurs; ++i) cout << queryMin(1, i, i) << ' '; cout << endl;*/ int posZero = findFirstZero(1, 0, nbValeurs - 1); assert(posZero != -1); get(posZero); } }; int disCircle(int x, int y) { if (x < y) return y - x; return nbPlantes - x + y; } void init(int _k, vector<int> r) { k = _k; nbPlantes = r.size(); for (int iPlante = 0; iPlante < nbPlantes; ++iPlante) { nbPlusGrands[iPlante] = r[iPlante]; } Seg segMax(r); for (int i = 0; i < nbPlantes; ++i) r[i] = k - 1 - r[i]; Seg segMin(r); orderLarge.resize(nbPlantes); orderSmall.resize(nbPlantes); for (int i = 0; i < nbPlantes; ++i) { orderLarge[segMax.order[i]] = nbPlantes - 1 - i; orderSmall[segMin.order[i]] = i; } /*for (auto v : orderLarge) cout << v << ' '; cout << endl; for (auto v : orderSmall) cout << v << ' '; cout << endl;*/ } int compare_plants(int x, int y) { if (x > y) return -compare_plants(y, x); if (orderSmall[x] > orderSmall[y]) return 1; if (orderLarge[x] < orderLarge[y]) 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...