题目大意:
先给定一大堆数字,(下标从1开始!!! 我当从0了,WA掉了2次!)
然后给定区间[L, R]问[L,R]区间内,第K大的数字是谁。
先预先读取所有区间,把区间排序。 然后保证平衡树内只有区间内的元素…… 然后每次直接把区间内的元素问题解决掉……时间复杂度略高nlogn而且n特别大,跑了5秒多
2761 | Accepted | 4124K | 5157MS | G++ | 3421B |
#include <cstring> #include <cstdio> #include <algorithm> using namespace std; const int max_n = 100005; const int maxint = 0x7fffffff; struct node { node *c[2]; int key, size; node () { key = size = 0; c[0] = c[1] = this; } node (int KEY_, node *c0, node *c1) { key = KEY_; c[0] = c0; c[1] = c1; } node* rz(){return size = c[0] -> size + c[1] -> size + 1, this;} }Tnull, *null = &Tnull; struct splay { node *root; splay() { root = (new node(*null)) -> rz(); root -> key = maxint; } void zig(int d) { node *t = root -> c[d]; root ->c[d] = null -> c[d]; null -> c[d] = root; root = t; } void zigzig(int d) { node *t = root -> c[d] -> c[d]; root -> c[d] -> c[d] = null -> c[d]; null -> c[d] = root -> c[d]; root -> c[d] = null -> c[d] -> c[!d]; null -> c[d] -> c[!d] = root -> rz(); root = t; } void finish(int d) { node *t = null -> c[d], *p = root -> c[!d]; while (t != null) { t = null -> c[d] -> c[d]; null -> c[d] -> c[d] = p; p = null -> c[d] -> rz(); null -> c[d] = t; } root -> c[!d] = p; } void select(int k) { int t; while (1) { bool d = k > (t = root -> c[0] -> size); if (k == t || root -> c[d] == null) break; if (d) k -= t + 1; bool dd = k > (t = root -> c[d] -> c[0] -> size); if (k == t || root -> c[d] -> c[dd] == null) {zig(d); break;} if (dd) k-= t+ 1; d != dd? zig(d), zig(dd) : zigzig(d); } finish(0), finish(1); root -> rz(); } void search(int x) { while (1) { bool d = x > root -> key; if (root -> c[d] == null) break; bool dd = x > root -> c[d] -> key; if (root -> c[d] -> c[dd] == null){zig(d); break;} d != dd ? zig(d), zig(dd) : zigzig(d); } finish(0), finish(1); root -> rz(); if (x > root -> key) select(root -> c[0] -> size + 1); } void ins(int x) { search(x); node *oldroot = root; root = new node(x, oldroot -> c[0], oldroot); oldroot -> c[0] = null; oldroot -> rz(); root -> rz(); } void del(int x) { search(x); node *oldroot = root; root = root -> c[1]; select(0); root -> c[0] = oldroot -> c[0]; root -> rz(); delete oldroot; } int sel(int k){return select(k -1), root -> key;} int ran(int x){return search(x), root -> c[0] -> size + 1;} }sp; struct question { int L, R; int k; int ans; int wz; }a[50005]; int save[max_n]; bool operator < (question A, question B) { if (A.L == B.L) return A.R < B.R; return A.L < B.L; } int n, q; void init() { scanf("%d%d", &n, &q); for (int i = 1; i <= n; ++ i) scanf("%d", &save[i]); for (int i = 0; i != q; ++ i) { scanf("%d%d%d", &a[i].L, &a[i].R, &a[i].k); a[i].wz = i; } sort(a, a + q); } int output[50005]; void doit() { int just_L, just_R, now_L, now_R; just_L = a[0].L; just_R = a[0].L - 1; for (int i = 0; i != q; ++ i) { now_L = a[i].L; now_R = a[i].R; for (int j = just_L; j != now_L; ++ j) sp.del(save[j]); for (int j = just_R + 1; j <= now_R; ++ j) sp.ins(save[j]); if (now_R < just_R) for (int j = now_R + 1; j <= just_R; ++ j) sp.del(save[j]); output[a[i].wz] = sp.sel(a[i].k); just_L = now_L; just_R = now_R; } for (int i = 0; i != q; ++ i) printf("%d\n",output[i]); } int main() { init(); doit(); return 0; }