树套树基础题。
我用线段树套无旋treap解决的这道题。
用线段树维护区间,每个线段树节点内部是一棵平衡树, 平衡树内存储区间[L,R]的节点信息。
不开O2会T掉一个点...可能是我自带大常数...
但自我感觉实现得非常优美...
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> using namespace std; #define reg register inline int read() { int res = 0;char ch = getchar();bool fu = 0; while(!isdigit(ch)) fu |= (ch == '-'), ch = getchar(); while(isdigit(ch)) res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar(); return fu ? -res : res; } #define N 500005 int n, m, chushi[N], MAX; namespace treap { int val[N * 50], siz[N * 50], ch[N * 50][2], pri[N * 50], tot; inline void update(int o) { siz[o] = siz[ch[o][0]] + siz[ch[o][1]] + 1; } inline int newnode(int v) { int jd = ++tot; siz[jd] = 1; val[jd] = v, pri[jd] = rand(); return jd; } int Merge(int x, int y) { if (x * y == 0) return x + y; if (pri[x] < pri[y]) { ch[x][1] = Merge(ch[x][1], y); update(x); return x; } else { ch[y][0] = Merge(x, ch[y][0]); update(y); return y; } } void Split(int o, int k, int &x, int &y) { if (!o) {x = y = 0;return;} if (val[o] <= k) x = o, Split(ch[x][1], k, ch[x][1], y); else y = o, Split(ch[y][0], k, x, ch[y][0]); update(o); } inline void insert(int &root, int v) { int a = 0, b = 0; Split(root, v, a, b); root = Merge(Merge(a, newnode(v)), b); } inline void delet(int &root, int v) { int a = 0, b = 0, c = 0; Split(root, v, a, b); Split(a, v - 1, a, c); c = Merge(ch[c][0], ch[c][1]); root = Merge(Merge(a, c), b); } inline int rnk(int &root, int v) { int a = 0, b = 0; Split(root, v - 1, a, b); int res = siz[a] - 1;// root = Merge(a, b); return res; } inline int kth(int o, int k) { while(1) { if (siz[ch[o][0]] >= k) o = ch[o][0]; else if (siz[ch[o][0]] + 1 == k) return val[o]; else k -= siz[ch[o][0]] + 1, o = ch[o][1]; } } inline int findpre(int &root, int v) { int a = 0, b = 0; Split(root, v - 1, a, b); int res = kth(a, siz[a]); root = Merge(a, b); return res; } inline int findnxt(int &root, int v) { int a = 0, b = 0; Split(root, v, a, b); int res = kth(b, 1); root = Merge(a, b); return res; } } int rt[N << 2]; #define ls o << 1 #define rs o << 1 | 1 void Build(int l, int r, int o) { treap::insert(rt[o], 2147483647); treap::insert(rt[o], -2147483647); for (reg int i = l ; i <= r ; i ++) treap :: insert(rt[o], chushi[i]); if (l == r) return ; int mid = (l + r) >> 1; Build(l, mid, ls), Build(mid + 1, r, rs); } int queryrank(int l, int r, int o, int ql, int qr, int v) { if (l >= ql and r <= qr) return treap::rnk(rt[o], v); int res = 0; int mid = (l + r) >> 1; if (ql <= mid) res += queryrank(l, mid, ls, ql, qr, v); if (qr > mid) res += queryrank(mid + 1, r, rs, ql, qr, v); return res; } inline int kth(int ql, int qr, int k) { int l = 0, r = MAX; int res = 0; while(l <= r) { int mid = (l + r) >> 1; if (queryrank(1, n, 1, ql, qr, mid) + 1 <= k) res = mid, l = mid + 1; else r = mid - 1; } return res; } void change(int l, int r, int o, int pos, int v, int yuanshi) { if (l == r) {treap::delet(rt[o], chushi[l]), chushi[l] = v, treap::insert(rt[o], v);return;} treap::delet(rt[o], yuanshi), treap::insert(rt[o], v); int mid = (l + r) >> 1; if (pos <= mid) change(l, mid, ls, pos, v, yuanshi); else change(mid + 1, r, rs, pos, v, yuanshi); } int ans; void querypre(int l, int r, int o, int ql, int qr, int v) { if (l >= ql and r <= qr) {ans = max(ans, treap::findpre(rt[o], v));return;} int mid = (l + r) >> 1; if (ql <= mid) querypre(l, mid, ls, ql, qr, v); if (qr > mid) querypre(mid + 1, r, rs, ql, qr, v); } void querynxt(int l, int r, int o, int ql, int qr, int v) { if (l >= ql and r <= qr) {ans = min(ans, treap::findnxt(rt[o], v));return;} int mid = (l + r) >> 1; if (ql <= mid) querynxt(l, mid, ls, ql, qr, v); if (qr > mid) querynxt(mid + 1, r, rs, ql, qr, v); } int main() { n = read(), m = read(); for (reg int i = 1 ; i <= n ; i ++) chushi[i] = read(), MAX = max(MAX, chushi[i]); Build(1, n, 1); while(m--) { int opt = read(), l = 0, r = 0, p = 0, v = 0; if (opt == 1) l = read(), r = read(), v = read(), printf("%d ", queryrank(1, n, 1, l, r, v) + 1); else if (opt == 2) l = read(), r = read(), v = read(), printf("%d ", kth(l, r, v)); else if (opt == 3) p = read(), v = read(), change(1, n, 1, p, v, chushi[p]); else if (opt == 4) l = read(), r = read(), v = read(), ans = -2147483647, querypre(1, n, 1, l, r, v), printf("%d ", ans); else l = read(), r = read(), v = read(), ans = 2147483647, querynxt(1, n, 1, l, r, v), printf("%d ", ans); } return 0; }