思路:
十分经典的treap板子题
#include<cstdio> #include<iostream> #include<cstdlib> using namespace std; const int maxn = 100010; 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; } #define l(x) c[x][0] #define r(x) c[x][1] int rt = 0, tpn, v[maxn], c[maxn][2], R[maxn], sz[maxn], vn[maxn]; inline void update(const int &x){ sz[x] = sz[l(x)] + sz[r(x)] + vn[x]; } inline void zap(int &x){ int t = r(x); r(x) = l(t); l(t) = x; update(x); update(t); x = t; } inline void zip(int &x){ int t = l(x); l(x) = r(t); r(t) = x; update(x); update(t); x = t; } void insert(int &x, int w){ if(!x){x = ++tpn; v[x] = w; R[x] = rand(); vn[x] = sz[x] = 1; return ;} if(w != v[x]) insert(c[x][v[x] < w], w); else vn[x]++; update(x); if(l(x) && R[l(x)] < R[x]) zip(x); if(r(x) && R[r(x)] < R[x]) zap(x); } void pop(int &x, int w){ if(v[x] != w) pop(c[x][v[x] < w], 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)]) zip(x), pop(x, w); else zap(x), pop(x, w); } } update(x); } 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 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 pre(int x, int w){ int res; while(x){ if(v[x] < w) res = v[x], x = r(x); else x = l(x); } return res; } int nxt(int x, int w){ int res; while(x){ if(v[x] <= w) x = r(x); else res = v[x], x = l(x); } return res; } int main(void) { srand(11535); int n; qread(n); while(n--){ int op, x; qread(op); qread(x); switch(op){ case 1: insert(rt, x); break; case 2: pop(rt, x); break; case 3: printf("%d\n", findr(rt, x)); break; case 4: printf("%d\n", findk(rt, x)); break; case 5: printf("%d\n", pre(rt, x)); break; case 6: printf("%d\n", nxt(rt, x)); break; } } }