【题目链接】
写的心累。。
将A操作看为降低工资底线,将S操作看为升高工资底线。那么这样就不用标记下传了。
另外一开始要加一个inf节点,不能再加个-inf节点,因为会被删掉...
写删除的时候要小心,根节点的删除和子树删除不一样。
/* Pigonometry */ #include <cstdio> #include <algorithm> using namespace std; const int maxn = 100005, inf = 0x3f3f3f3f; int n, lwb, delta, ans; inline int iread() { int f = 1, x = 0; char ch = getchar(); for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1; for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0'; return f * x; } int son[maxn][2], pre[maxn], val[maxn], size[maxn]; int tot1, tot2, sta[maxn], root; inline void newnode(int &x, int f, int c) { x = tot2 ? sta[tot2--] : ++tot1; son[x][0] = son[x][1] = 0; pre[x] = f; val[x] = c; size[x] = 1; } inline void pushup(int x) { size[x] = size[son[x][0]] + size[son[x][1]] + 1; } inline void init() { tot1 = tot2 = root = 0; son[0][0] = son[0][1] = pre[0] = val[0] = size[0] = 0; newnode(root, 0, inf); pushup(root); } inline void rotate(int x) { int y = pre[x], z = pre[y], type = son[y][1] == x; pre[son[y][type] = son[x][!type]] = y; pre[x] = z; if(z) son[z][son[z][1] == y] = x; pre[son[x][!type] = y] = x; pushup(y); pushup(x); } inline void splay(int x, int goal) { while(pre[x] != goal) { int y = pre[x], z = pre[y]; if(z == goal) rotate(x); else if(son[z][1] == y ^ son[x][1] == x) rotate(x), rotate(x); else rotate(y), rotate(x); } if(goal == 0) root = x; } inline int find(int k) { int x = root; while(k != size[son[x][0]] + 1) if(k <= size[son[x][0]]) x = son[x][0]; else k -= size[son[x][0]] + 1, x = son[x][1]; return x; } inline int insert(int c) { int now = root; for(; son[now][c > val[now]]; now = son[now][c > val[now]]); newnode(son[now][c > val[now]], now, c); splay(son[now][c > val[now]], 0); return root; } inline void trash(int x) { if(!x) return; trash(son[x][0]); trash(son[x][1]); son[x][0] = son[x][1] = pre[x] = val[x] = size[x] = 0; sta[++tot2] = x; } inline void del(int c) { int x = insert(c); splay(x, 0); ans += size[son[x][0]]; trash(son[x][0]); root = son[x][1]; pre[root] = 0; sta[++tot2] = x; pushup(root); } inline int findwage(int k) { k = size[root] - k; int x = find(k); return val[x]; } int main() { n = iread(); lwb = iread(); init(); while(n--) { char ch = getchar(); for(; ch < 'A' || ch > 'Z'; ch = getchar()); int k = iread(); if(ch == 'I') { if(k >= lwb) insert(k + delta); } else if(ch == 'A') delta -= k; else if(ch == 'S') { delta += k; del(lwb + delta); } else if(ch == 'F') { if(k > size[root] - 1) printf("-1\n"); else printf("%d\n", findwage(k) - delta); } } printf("%d\n", ans); return 0; }
附暴力和mkdata
#include <cstdio> #include <algorithm> using namespace std; const int maxn = 100005; int n, lwb, tot, ans, num[maxn]; inline int iread() { int f = 1, x = 0; char ch = getchar(); for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1; for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0'; return f * x; } inline bool cmp(int a, int b) { return a > b; } int main() { freopen("cashier.in", "r", stdin); freopen("cashier.ans", "w", stdout); n = iread(); lwb = iread(); ans = 0; while(n--) { char ch = getchar(); for(; ch < 'A' || ch > 'Z'; ch = getchar()); int k = iread(); if(ch == 'I') { if(k >= lwb) num[++tot] = k; } else if(ch == 'A') { for(int i = 1; i <= tot; i++) num[i] += k; } else if(ch == 'S') { sort(num + 1, num + 1 + tot, cmp); for(int i = 1; i <= tot; i++) { num[i] -= k; if(num[i] < lwb) ans += tot - i + 1, tot = i - 1; } } else if(ch == 'F') { if(k > tot) printf("-1\n"); else { sort(num + 1, num + 1 + tot, cmp); printf("%d\n", num[k]); } } } printf("%d\n", ans); return 0; }
#include <cstdio> #include <cstdlib> #include <ctime> using namespace std; const int maxv = 100; inline int rd(int x) { return rand() % x + 1; } int main() { srand(time(0)); freopen("cashier.in", "w", stdout); int n = 30, lwb = rd(maxv); printf("%d %d\n", n, lwb); while(n--) { int opt = rd(4); if(opt == 1) printf("I %d\n", rd(maxv) - 1); else if(opt == 2) printf("A %d\n", rd(maxv) - 1); else if(opt == 3) printf("S %d\n", rd(maxv) - 1); else if(opt == 4) printf("F %d\n", rd(n + 100)); } return 0; }