Submission #110498

#TimeUsernameProblemLanguageResultExecution timeMemory
110498shoemakerjoCake (CEOI14_cake)C++14
51.67 / 100
2059 ms77344 KiB
#include <bits/stdc++.h> using namespace std; const int maxn = 250010; const int maxq = 500010; #define LEFT 0 #define RIGHT 1 #define pii pair<int, int> int n, q; int a; map<int, int> mval; //mamp from index to value int svals[maxn]; struct node { node *ch[2]; int indo; //either negative index or query time thing int we; //the random weight node *par; node(int ii) : indo(ii) { we = rand() % 1000000; ch[0] = ch[1] = NULL; par = NULL; } void setChild(int dir, node *c) { ch[dir] = c; // cout << this->indo << " :: " << c->indo << endl; if (c != NULL) { c->par = this; } } int getDirection() { if (par == NULL) return -1; if (this == par->ch[LEFT]) return LEFT; if (this == par->ch[RIGHT]) return RIGHT; return -1; } bool isroot() { return !par || (par->ch[LEFT] != this && par->ch[RIGHT] != this); } void rotateUp() { int dir = getDirection(); node *p = par; if (!p->isroot()) { p->par->ch[p->getDirection()] = this; } par = p->par; node *pMid = ch[!dir]; p->setChild(dir, pMid); setChild(!dir, p); } }; node *cnodes[maxn]; //current nodes node *root = NULL; string tp[maxq]; int qv[maxq][2]; vector<int> inorder; int seg[maxn*4]; //we want to store a maximum seg tree void update(int spot, int val, int ss = 1, int se = n, int si = 0) { if (spot > se || spot < ss || ss > se) return; if (ss == se) { seg[si] = val; return; } int mid = (ss+se)/2; if (spot <= mid) { update(spot, val, ss, mid, si*2+1); } else update(spot, val, mid+1, se, si*2+2); seg[si] = max(seg[si*2+1], seg[si*2+2]); } int query(int qs, int qe, int ss = 1, int se = n, int si = 0) { if (qs > qe || ss > se || qs > se || qe < ss) return 0; if (qs <= ss && se <= qe) return seg[si]; int mid = (ss+se)/2; return max(query(qs, qe, ss, mid, si*2+1), query(qs, qe, mid+1, se, si*2+2)); } void buildtree(int ss = 1, int se = n, int si = 0) { if (ss == se) { // cout << " here " << ss << " : " << mval[0-ss] << endl; seg[si] = mval[0-ss]; return; } int mid = (ss+se)/2; buildtree(ss, mid, si*2+1); buildtree(mid+1, se, si*2+2); seg[si] = max(seg[si*2+1], seg[si*2+2]); } vector<pii> befa; vector<pii> afta; void dfs(node *cur) { // cout << "at: " << cur->indo << endl; if (cur->ch[LEFT]) { dfs(cur->ch[LEFT]); } inorder.push_back(cur->indo); if (cur->ch[RIGHT]) { dfs(cur->ch[RIGHT]); } } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); srand(time(NULL)); cin >> n >> a; vector<pii> stuff; for (int i = 1; i <= n; i++) { cin >> svals[i]; stuff.push_back(pii(svals[i], i)); } cin >> q; sort(stuff.begin(), stuff.end()); reverse(stuff.begin(), stuff.end()); for (pii vp : stuff) { int ind = vp.second; node *cur = new node(0-ind); cnodes[ind] = cur; if (root == NULL) { root = cur; continue; } //insert me to be the smallest guy present node *tmp = root; while (tmp->ch[LEFT] != NULL) { tmp = tmp->ch[LEFT]; } tmp->setChild(LEFT, cur); //now we need to rotate cur up a bunch while (!cur->isroot() && cur->we > cur->par->we) { cur->rotateUp(); } if (cur->isroot()) { root = cur; } } //store the ten greatest values at any time vector<int> tg; for (int i = 0; i < 10 && i < stuff.size(); i++) { tg.push_back(stuff[i].second); } for (int i = 0; i < q; i++) { // cout << " at start of " << i << " root is: " << root->indo << endl; cin >> tp[i]; if (tp[i] == "E") { cin >> qv[i][0] >> qv[i][1]; int ind = qv[i][0]; int ec = qv[i][1]; for (int i = 0; i < tg.size(); i++) { if (tg[i] == ind) { tg.erase(tg.begin() + i); } } tg.insert(tg.begin() + ec-1, ind); node *cur = new node(i); cnodes[ind] = cur; if (ec == 1) { //insert this to be the biggest value we have node *tmp = root; while (tmp->ch[RIGHT] != NULL) { tmp = tmp->ch[RIGHT]; } tmp->setChild(RIGHT, cur); } else { int aft = tg[ec-2]; //want to be right below this guy node *tmp = cnodes[aft]; // cout << "THIS: " << tmp->indo << endl; if (tmp->ch[LEFT] == NULL) { tmp->setChild(LEFT, cur); } else { tmp = tmp->ch[LEFT]; while (tmp->ch[RIGHT] != NULL) { tmp = tmp->ch[RIGHT]; } tmp->setChild(RIGHT, cur); } } while (!cur->isroot() && cur->we > cur->par->we) { cur->rotateUp(); } if (cur->isroot()) { root = cur; } } else { cin >> qv[i][0]; //do not really want to do anything } // cout << "done with index: " << i << endl; } // vector<int> find; tg.clear(); for (int i = 0; i < 10 && i < stuff.size(); i++) { tg.push_back(stuff[i].second); } dfs(root); // cout << "inorder: "; for (int i = 0; i < inorder.size(); i++) { int v = inorder[i]; // cout << v << " "; mval[v] = i+1; } // cout << endl; buildtree(); // cout << "START: " << query(1, n) << endl; //now we must process the queries for (int i = a-1; i >= 1; i--) { if (befa.size() && befa.back().first >= mval[0-i]) { continue; } befa.push_back(pii(mval[0-i], i)); } befa.push_back(pii(10000000, 0)); for (int i = a+1; i <= n; i++) { if (afta.size() && afta.back().first >= mval[0-i]) { continue; } afta.push_back(pii(mval[0-i], i)); } afta.push_back(pii(10000000, n+1)); for (int ii = 0; ii < q; ii++) { if (tp[ii] == "E") { int mv = mval[ii]; int cind = qv[ii][0]; update(cind, mv); if (cind < a) { //update befa for (int i = befa.size()-1; i >= 0; i--) { if (befa[i].second > cind) { if (befa[i].first < mv) { befa.insert(befa.begin() + i+1, pii(mv, cind)); } break; //do not want to do this } if (befa[i].first <= mv) { befa.erase(befa.begin() + i); } if (i == 0) { befa.insert(befa.begin() + 0, pii(mv, cind)); } } } if (cind > a) { //update afta for (int i = afta.size()-1; i >= 0; i--) { if (afta[i].second < cind) { if (afta[i].first < mv) { afta.insert(afta.begin() + i+1, pii(mv, cind)); } break; //do not want to do this } if (afta[i].first <= mv) { afta.erase(afta.begin() + i); } if (i == 0) { afta.insert(afta.begin() + 0, pii(mv, cind)); } } } } else { int mq = qv[ii][0]; if (mq == a) { cout << 0 << '\n'; } else if (mq < a) { int bg = query(mq, a-1); //binary search to find first ind greater than me int lo = 0, hi = afta.size()-1; while (lo < hi) { int mid = (lo + hi)/2; if (afta[mid].first > bg) { hi = mid; } else lo = mid+1; } // if (ii == 0) cout << " value : " << bg << endl; // if (ii == 0) cout << lo << " : " << befa[lo].second << endl; int res = afta[lo].second - mq - 1; cout << res << '\n'; } else if (mq > a) { int bg = query(a+1, mq); int lo = 0, hi = befa.size()-1; while (lo < hi) { int mid = (lo + hi)/2; if (befa[mid].first > bg) { hi = mid; } else lo = mid+1; } int res = mq - befa[lo].second - 1; cout << res << '\n'; } } } cout.flush(); }

Compilation message (stderr)

cake.cpp: In function 'int main()':
cake.cpp:171:31: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for (int i = 0; i < 10 && i < stuff.size(); i++) {
                             ~~^~~~~~~~~~~~~~
cake.cpp:184:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
       for (int i = 0; i < tg.size(); i++) {
                       ~~^~~~~~~~~~~
cake.cpp:236:31: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for (int i = 0; i < 10 && i < stuff.size(); i++) {
                             ~~^~~~~~~~~~~~~~
cake.cpp:242:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for (int i = 0; i < inorder.size(); i++) {
                   ~~^~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...