splay

普通平衡树

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; int read(void) {
int x = 0; bool f = 0;
char c = getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
for (;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^48);
if (f) return -x;
return x;
} const int N = 100005;
const int INF = 0x7fffffff;
int v[N], f[N], son[N][2];
int cnt[N], siz[N], tot;
int val[N], n, sz, root; inline void update(int x) {
siz[x] = siz[son[x][0]] + siz[son[x][1]] + cnt[x];
} inline void rotate(int x) {
int y = f[x], z = f[y];;
int k = son[f[x]][1] == x, w = son[x][k^1];
son[y][k] = w, f[w] = y;
son[z][son[z][1] == y] = x, f[x] = z;
son[x][k^1] = y, f[y] = x;
update(y), update(x);
} inline void splay(int x,int t) {
while (f[x] != t) {
int y = f[x], z = f[y];
if (z != t) {
if ((son[y][1] == x) ^ (son[z][1] == y))
rotate(x);
else rotate(y);
}
rotate(x);
}
if (t == 0) root = x;
} inline void insert(int x) {
int p = root, pre = 0;
while (p && val[p] != x)
pre = p, p = son[p][val[p] < x];
if (p) cnt[p]++;
else {
p = ++sz; cnt[p] = siz[p] = 1;
if (pre) son[pre][val[pre] < x] = p;
son[p][0] = son[p][1] = 0;
f[p] = pre, val[p] = x;
}
splay(p, 0);
} inline void find(int x) {
int p = root;
while (son[p][val[p] < x] && val[p] != x)
p = son[p][val[p] < x];
splay(p, 0);
} inline int get_rk(int x) {
find(x);
return siz[son[root][0]];
} inline int kth(int x) {
int p = root; x++;
while (true) {
if (son[p][0] && x <= siz[son[p][0]]) p = son[p][0];
else if (x > siz[son[p][0]] + cnt[p])
x -= siz[son[p][0]] + cnt[p], p = son[p][1];
else return val[p];
}
} inline int get_pre(int x) {
find(x);
if (val[root] < x) return root;
int p = son[root][0];
while (son[p][1]) p = son[p][1];
return p;
} inline int get_nxt(int x) {
find(x);
if (val[root] > x) return root;
int p = son[root][1];
while (son[p][0]) p = son[p][0];
return p;
} inline void del(int x) {
int pre = get_pre(x), nxt = get_nxt(x);
splay(pre, 0), splay(nxt, root);
int p = son[nxt][0];
if (cnt[p] > 1) cnt[p]--, splay(p, 0);
else son[nxt][0] = 0, update(nxt), update(root);
} int main() {
int opt, x; n = read();
insert(INF), insert(-INF);
for (int i = 1;i <= n; i++) {
opt = read(), x = read();
if (opt == 1) insert(x);
else if (opt == 2) del(x);
else if (opt == 3) printf ("%d\n", get_rk(x));
else if (opt == 4) printf ("%d\n", kth(x));
else if (opt == 5) printf ("%d\n", val[get_pre(x)]);
else printf ("%d\n", val[get_nxt(x)]);
}
return 0;
}

文艺平衡树

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 200050;
const int INF = 0x7fffffff;
int read(void) {
int x = 0; bool f = 0;
char c = getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
for (;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^48);
return f ? -x : x;
} int val[N], son[N][2];
int tag[N], f[N], n, sz;
int siz[N], rt; void update(int x) {
siz[x] = siz[son[x][1]] + siz[son[x][0]] + 1;
} void spread(int x) {
if (!tag[x]) return;
swap(son[x][0], son[x][1]);
if (son[x][0]) tag[son[x][0]] ^= 1;
if (son[x][1]) tag[son[x][1]] ^= 1;
tag[x] = 0;
} int kth(int k) {
int x = rt;
while (true) {
spread(x);
if (siz[son[x][0]] >= k) x = son[x][0];
else if (siz[son[x][0]] + 1 == k) return x;
else k -= siz[son[x][0]] + 1, x = son[x][1];
}
} void rotate(int x) {
int y = f[x], z = f[y];
int k = son[y][1] == x, w = son[x][k^1];
son[y][k] = w, f[w] = y;
f[y] = x, son[x][k^1] = y;
son[z][son[z][1]==y] = x, f[x] = z;
update(y), update(x);
} void splay(int x,int t) {
while (f[x] != t) {
int y = f[x], z = f[y];
if (z != t) {
if ((son[z][1]==y)^(son[y][1]==x))
rotate(x);
else rotate(y);
}
rotate(x);
}
if (t == 0) rt = x;
} void insert(int x) {
int p = rt, pre = 0;
while (p)
pre = p, p = son[p][val[p] < x];
p = ++sz;
if (pre) son[pre][val[pre]<x] = p;
siz[p] = 1, son[p][0] = son[p][1] = 0;
f[p] = pre, val[p] = x;
splay(p, 0);
} void rec(int x) {
spread(x);
if (son[x][0]) rec(son[x][0]);
if (val[x] > 1 && val[x] < n + 2)
printf ("%d ", val[x]-1);
if (son[x][1]) rec(son[x][1]);
} inline void work(int l,int r) {
l = kth(l), r = kth(r+2);
splay(l, 0); splay(r, rt);
tag[son[son[rt][1]][0]] ^= 1;
} int m, l, r;
int main() {
n = read(), m = read();
for (int i = 1;i <= n + 2; i++)
insert(i);
while (m--) {
l = read(), r = read();
work(l, r);
}
rec(rt);
cout << endl;
return 0;
}

fhq板子(代码正确且风格易懂)

洛谷P3369

#include<iostream>
#include<cstring>
#include<cstdio>
#include<ctime>
#include<cstdlib>
using namespace std;
const int N = 105000;
int val[N], son[N][2];
int rnd[N], tot, n;
int siz[N], root, a, p, x, y, z;
inline void update(int x) {
siz[x] = siz[son[x][1]] + siz[son[x][0]] + 1;
}
inline int build(int x) {
siz[++tot] = 1, rnd[tot] = rand();
val[tot] = x; return tot;
}
int merge(int x,int y) {
if (!x || !y) return x + y;
if (rnd[x] < rnd[y]) {
son[x][1] = merge(son[x][1], y);
update(x); return x;
}
son[y][0] = merge(x, son[y][0]);
update(y); return y;
}
void split(int now,int k,int &x,int &y) {
if (!now) x = y = 0;
else {
if (val[now] <= k) x = now, split(son[x][1], k, son[x][1], y);
else y = now, split(son[y][0], k, x, son[y][0]);
update(now);
}
} inline int kth(int now, int k) {
while (1) {
if (k <= siz[son[now][0]]) now = son[now][0];
else if (k == siz[son[now][0]] + 1) return now;
else k -= siz[son[now][0]] + 1, now = son[now][1];
}
}
template <typename T>
void read(T &x) {
x = 0; int f = 1;char c = getchar();
while (!isdigit(c)) { if (c == '-') f = -1; c = getchar();}
while (isdigit(c)) { x = (x << 3)+(x << 1) + c-'0'; c = getchar();}
x *= f;
}
int main() {
srand(time(0));
read(n);
for (int i = 1;i <= n; i++) {
read(p), read(a);
if (p == 1) {
split(root, a, x, y);
root = merge(merge(x, build(a)), y);
}
else if (p == 2) {
split(root, a, x, y);
split(x, a-1, x, z);
z = merge(son[z][0], son[z][1]);
root = merge(merge(x, z), y);
}
else if (p == 3) {
split(root, a-1, x, y);
printf ("%d\n", siz[x] + 1);
root = merge(x, y);
}
else if (p == 4) printf ("%d\n", val[kth(root, a)]);
else if (p == 5) {
split(root, a-1, x, y);
printf ("%d\n", val[kth(x, siz[x])]);
root = merge(x, y);
}
else {
split(root, a, x, y);
printf ("%d\n", val[kth(y, 1)]);
root = merge(x, y);
}
}
return 0;
}

洛谷P3391

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<ctime>
using namespace std;
const int N = 100050;
int rnd[N], siz[N];
int cnt, n, l, r;
int tag[N], son[N][2];
int val[N], root, x, y, z;
inline int build(int x) {
siz[++cnt] = 1, val[cnt] = x;
rnd[cnt] = rand(); return cnt;
}
inline void update(int x) {
siz[x] = siz[son[x][1]] + siz[son[x][0]] + 1;
}
void spread(int x) {
if (tag[x]) {
swap(son[x][0], son[x][1]);
if (son[x][0]) tag[son[x][0]] ^= 1;
if (son[x][1]) tag[son[x][1]] ^= 1;
tag[x] = 0;
}
}
void split(int now,int k,int &x,int &y) {
if (!now) x = y = 0;
else {
spread(now);
if (siz[son[now][0]] < k) x = now, split(son[x][1], k - siz[son[now][0]] - 1, son[x][1], y);
else y = now, split(son[y][0], k, x, son[y][0]);
update(now);
}
}
int merge(int x,int y) {
if(!x || !y) return x + y;
if (rnd[x] < rnd[y]) {
spread(x);
son[x][1] = merge(son[x][1], y);
update(x); return x;
}
spread(y);
son[y][0] = merge(x, son[y][0]);
update(y); return y;
}
template <typename T>
void read(T &x) {
x = 0; int f = 1;char c = getchar();
while (!isdigit(c)) { if (c == '-') f = -1; c = getchar();}
while (isdigit(c)) { x = (x << 3)+(x << 1) + c-'0'; c = getchar();}
x *= f;
}
int m;
void res(int x) {
if (!x) return;
spread(x);
res(son[x][0]);
printf ("%d ", val[x]);
res(son[x][1]);
}
int main() {
read(n), read(m);
for (int i = 1;i <= n; i++) root = merge(root, build(i));
while (m--) {
read(l), read(r);
split(root, l - 1, x, y);
split(y, r - l+ 1, y, z);
tag[y] ^= 1;
root = merge(merge(x, y), z);
}
res(root);
return 0;
}

可持久化平衡树

p3835

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<cstring>
using namespace std;
const int N = 500500 * 50;
const int INF = 2147483647;
int T[N], val[N], rnd[N];
int siz[N], son[N][2];
int cnt; template <typename T>
void read(T &x) {
x = 0; int f = 1;char c = getchar();
while (!isdigit(c)) { if (c == '-') f = -1; c = getchar();}
while (isdigit(c)) { x = (x << 3)+(x << 1) + c-'0'; c = getchar();}
x *= f;
} inline void update(int x) {
siz[x] = siz[son[x][0]] + siz[son[x][1]] + 1;
} inline void cpy(int x,int y) {
siz[x] = siz[y], son[x][1] = son[y][1];
son[x][0] = son[y][0];
val[x] = val[y], rnd[x] = rnd[y];
}
inline int build(int x) {
val[++cnt] = x, siz[cnt] = 1;
rnd[cnt] = rand(); return cnt;
} void split(int now,int k,int &x,int &y) {
if (!now) x = y = 0;
else {
if (val[now] <= k) {
x = ++cnt, cpy(x, now), split(son[x][1], k, son[x][1], y);
update(x);
}
else {
y = ++cnt, cpy(y, now), split(son[y][0], k, x, son[y][0]);
update(y);
}
}
} int merge(int x,int y) {
if (!x || !y) return x + y;
if (rnd[x] < rnd[y]) {
int p = ++cnt; cpy(p, x);
son[p][1] = merge(son[p][1], y);
update(p); return p;
}
int p = ++cnt; cpy(p, y);
son[p][0] = merge(x, son[p][0]);
update(p); return p;
} int kth(int now,int x) {
while (1) {
if (siz[son[now][0]] >= x) now = son[now][0];
else if (siz[son[now][0]] + 1 == x) return now;
else x -= siz[son[now][0]] + 1, now = son[now][1];
}
} int n, x, y, z;
int op, P, a;
int main() {
srand(20040202);
read(n);
for (int i = 1;i <= n; i++) {
read(P), read(op), read(a);
T[i] = T[P];
if (op == 1) {
split(T[i], a, x, y);
T[i] = merge(merge(x, build(a)), y);
}
else if (op == 2) {
split(T[i], a, x, z);
split(x, a-1, x, y);
y = merge(son[y][0], son[y][1]);
T[i] = merge(merge(x, y), z);
}
else if (op == 3) {
split(T[i], a-1, x, y);
printf ("%d\n", siz[x] + 1);
T[i] = merge(x, y);
}
else if (op == 4) printf ("%d\n", val[kth(T[i], a)]);
else if (op == 5) {
split(T[i], a-1, x, y);
if (siz[x] == 0) printf ("%d\n", -INF);
else printf ("%d\n", val[kth(x, siz[x])]);
T[i] = merge(x, y);
}
else if (op == 6) {
split(T[i], a, x, y);
if (siz[y] == 0) printf ("%d\n", INF);
else printf ("%d\n", val[kth(y, 1)]);
T[i] = merge(x, y);
}
}
return 0;
}

平衡树(fhq无旋treap)的更多相关文章

  1. 【序列操作V】平衡树(无旋treap)

    题目描述 维护一个队列,初始为空.依次加入 n(1≤n≤105)个数 ai(-109≤ai≤109),第 i(1≤i≤n)个数加入到当前序列第 bi(0≤bi≤当前序列长度)个数后面.输出最终队列. ...

  2. [Bzoj3223][Tyvj1729] 文艺平衡树(splay/无旋Treap)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3223 平衡树处理区间问题的入门题目,普通平衡树那道题在维护平衡树上是以每个数的值作为维护 ...

  3. [Bzoj3224][Tyvj1728] 普通平衡树(splay/无旋Treap)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3224 平衡树入门题,学习学习. splay(学习yyb巨佬) #include<b ...

  4. BZOJ - 3223 Tyvj 1729 文艺平衡树 (splay/无旋treap)

    题目链接 splay: #include<bits/stdc++.h> using namespace std; typedef long long ll; ,inf=0x3f3f3f3f ...

  5. 浅谈无旋treap(fhq_treap)

    一.简介 无旋Treap(fhq_treap),是一种不用旋转的treap,其代码复杂度不高,应用范围广(能代替普通treap和splay的所有功能),是一种极其强大的平衡树. 无旋Treap是一个叫 ...

  6. Luogu 3369 / BZOJ 3224 - 普通平衡树 - [无旋Treap]

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=3224 https://www.luogu.org/problemnew/show/P3 ...

  7. [转载]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)

    转载自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182491.html 今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和t ...

  8. [您有新的未分配科技点]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)

    今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和treap一样简单易懂,同时还支持可持久化. 无旋treap的节点定义和treap一样,都要同时满足树性质和堆性质,我 ...

  9. [BZOJ3223]文艺平衡树 无旋Treap

    3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Description 您需要写一种数据结构(可参考题目标题),来维护一个 ...

随机推荐

  1. Rest_Framework简介

    Web应用模式 在开发Web应用中,有两种应用模式:前后端不分离和前后端分离 前后端不分离 前后端不分离通俗来讲就是不区分前端和后端,浏览器请求时服务器直接返回页面,其示意图如下 前后端分离 前后端分 ...

  2. ASP.NET MVC5入门指南(1)*入门介绍

    以下指南说明了什么是ASP.NET MVC,并说明了如何入门. ASP.NET MVC 5入门 入门 添加控制器 添加视图 添加模型 创建连接字符串并使用SQL Server LocalDB 从控制器 ...

  3. JavaScript基础——JavaScript数据类型(笔记)

    数据类型(笔记) null和undefined 在JavaScript中有两个特殊的值: null和undefined.简单说明如下: null 是Null类型的值,Null类型的值只有一个值(nul ...

  4. python读取文件出现\ufeff问题

    现象: 读取csv文件,表头为'ID',但读取后显示'\ufeffID',所以使用dict['ID']读取会报错 原因: 该文件保存时保存了BOM,保存于文件头部 解决: 将原有的 file_cont ...

  5. CSS3 的背景属性

    ㈠background-size 属性 ⑴background-size 属性规定背景图片的尺寸. ⑵在 CSS3 之前,背景图片的尺寸是由图片的实际尺寸决定的.在 CSS3 中,可以规定背景图片的尺 ...

  6. Oracle 表锁定

    --锁表查询SQL SELECT object_name, machine, s.sid, s.serial# FROM gv$locked_object l, dba_objects o, gv$s ...

  7. 计蒜客 2018南京网络赛 I Skr ( 回文树 )

    题目链接 题意 : 给出一个由数字组成的字符串.然后要你找出其所有本质不同的回文子串.然后将这些回文子串转化为整数后相加.问你最后的结果是多少.答案模 1e9+7 分析 : 应该可以算是回文树挺裸的题 ...

  8. Nowcoder farm ( 树状数组、二维前缀和、二维偏序 )

    题目链接 分析 : 最简单的想法当然就是去模拟 直接对每个施肥料的操作进行模拟.然后计算贡献 但是这显然会超时.这题需要换一个思维 对于一个土地(也就是二维平面上的一个点)的种类是 T' 如果它被操作 ...

  9. 翻页的时候更改URL地址

    要求点击第一页是url+p1html,点击第二页是url+p2html等等 $("body").on('click','#w_tagPage a[wid]',function(){ ...

  10. javascript中的原型和原型链(五)

    Array.prototype 先记住一句话——每一个函数,都有一个prototype属性——每一个函数,无论是你自定义的,还是系统内置的 var fn = function() {} console ...