• 注册
当前位置:1313e > 默认分类 >正文

树套树模板 (二逼平衡树)

树套树基础题。

我用线段树套无旋treap解决的这道题。

用线段树维护区间,每个线段树节点内部是一棵平衡树, 平衡树内存储区间[L,R]的节点信息。

不开O2会T掉一个点...可能是我自带大常数...

但自我感觉实现得非常优美...

#include 
#include 
#include 
#include 
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\n", queryrank(1, n, 1, l, r, v) + 1);else if (opt == 2) l = read(), r = read(), v = read(), printf("%d\n", 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\n", ans);else l = read(), r = read(), v = read(), ans = 2147483647, querynxt(1, n, 1, l, r, v), printf("%d\n", ans);}return 0;
}

 

转载于:https://www.cnblogs.com/BriMon/p/10389499.html

本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 162202241@qq.com 举报,一经查实,本站将立刻删除。

最新评论

欢迎您发表评论:

请登录之后再进行评论

登录