思路:
简单的treap+模拟。
但这道题的题面有误导群众的嫌疑,因为题中并没有明确刚进入公司就离开的算不算在离开公司的人中。
当然,对于这道题的数据,题目意思是不算在内。
#include<cstdio> #include<iostream> #include<cstdlib> #include<string> using namespace std; const int maxn = 80010; inline void qread(int &x) { x = 0; register int ch = getchar(), flag = 0; while(ch < ‘0‘ || ch > ‘9‘) { if(ch == ‘-‘) flag = 1; ch = getchar(); } while(ch >= ‘0‘ && ch <= ‘9‘) x = 10 * x + ch - 48, ch = getchar(); if(flag) x = -x; } int rt = 0, tpn, v[maxn], l[maxn], r[maxn], R[maxn], sz[maxn], vn[maxn]; inline void update(int x) { sz[x] = sz[l[x]] + sz[r[x]] + vn[x]; } inline void zig(int &x) { int t = l[x]; l[x] = r[t]; r[t] = x; update(x); update(t); x = t; } inline void zag(int &x) { int t = r[x]; r[x] = l[t]; l[t] = x; update(x); update(t); x = t; } void insert(int &x, int w) { if(!x) { x = ++tpn; v[x] = w; R[x] = rand(); sz[x] = vn[x] = 1; return ; } if(w < v[x]) insert(l[x], w); else if(w > v[x]) insert(r[x], w); else vn[x]++; update(x); if(l[x] && R[l[x]] < R[x]) zig(x); if(r[x] && R[r[x]] < R[x]) zag(x); } void pop(int &x, int w) { if(w < v[x]) pop(l[x], w); else if(w > v[x]) pop(r[x], w); else { if(vn[x] > 1) vn[x]--; else if(!l[x] || !r[x]) x = l[x] | r[x]; else if(R[l[x]] < R[r[x]]) zig(x), pop(x, w); else zag(x), pop(x, w); } update(x); } int ask(int x, int w){ if(!x) return -1; if(w < v[x]) return ask(l[x], w); if(w > v[x]) return ask(r[x], w); return x; } int findr(int x, int w){ int res = 0; while(x){ if(v[x] == w) return res + sz[l[x]] + 1; if(v[x] > w) x = l[x]; else res += sz[l[x]] + vn[x], x = r[x]; } return res; } int findk(int x, int k){ if(k >= sz[l[x]] + 1 && k <= sz[l[x]] + vn[x]) return v[x]; if(k <= sz[l[x]]) return findk(l[x], k); return findk(r[x], k - sz[l[x]] - vn[x]); } int findpre(int x, int w){ int res = -0x3f3f3f3f; while(x){ if(w <= v[x]) x = l[x]; else res = v[x], x = r[x]; } return res; } int findnxt(int x, int w){ int res = 0x3f3f3f3f; while(x){ if(w < v[x]) res = v[x], x = l[x]; else x = r[x]; } return res; } int main(void) { srand(11535); int n, minn, nminn, ans = 0; qread(n); qread(minn); nminn = minn; while(n--){ string op; int k; cin >> op; qread(k); if(op == "I"){ if(k >= minn) insert(rt, k - minn + nminn); } else if(op == "A") nminn -= k; else if(op == "S"){ nminn += k; int t; while((t = findpre(rt, nminn)) != -0x3f3f3f3f) pop(rt, t), ans++; } else printf("%d\n", k > sz[rt] ? -1 : findk(rt, sz[rt] - k + 1) + minn - nminn); } printf("%d\n", ans); }
loj10145. 「一本通 4.6 练习 2」郁闷的出纳员
原文:https://www.cnblogs.com/junk-yao-blog/p/9483899.html