题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3223

平衡树处理区间问题的入门题目,普通平衡树那道题在维护平衡树上是以每个数的值作为维护的标准,而处理区间问题时,维护平衡树的应该是每个位置的下标,所以平衡树中序遍历时应该是当前区间的样子。例如:

{1 2 3 4 5}翻转区间1 3,则中序遍历应该输出{3,2,1,4,5}。

提供splay和无旋Treap的题解。

splay做法:

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 2e9;
const int maxn = ;
int ch[maxn][], siz[maxn], lazy[maxn], fa[maxn], val[maxn];
int a[maxn];
int root, cnt;
void pushup(int x) {
siz[x] = siz[ch[x][]] + siz[ch[x][]] + ;
}
void pushdown(int x) {
if (lazy[x]) {
if (ch[x][])lazy[ch[x][]] ^= ;
if (ch[x][])lazy[ch[x][]] ^= ;
swap(ch[x][], ch[x][]);
lazy[x] = ;
}
}
void rotate(int x) {//将x旋转到x的父亲的位置
int y = fa[x];
int z = fa[y];
pushdown(y); pushdown(x);
int k = (ch[y][] == x);
ch[z][ch[z][] == y] = x;
fa[x] = z;
ch[y][k] = ch[x][k ^ ];
fa[ch[x][k ^ ]] = y;
ch[x][k ^ ] = y;
fa[y] = x;
pushup(y); pushup(x);
}
void splay(int x, int goal) {//将x旋转为goal的子节点
while (fa[x] != goal) {
int y = fa[x];
int z = fa[y];
if (z != goal)
(ch[y][] == x) ^ (ch[z][] == y) ? rotate(x) : rotate(y);
//如果x和y同为左儿子或者右儿子先旋转y
//如果x和y不同为左儿子或者右儿子先旋转x
rotate(x);
}
if (goal == )
root = x;
}
int build(int l, int r, int f) {
if (l > r)return ;
int mid = l + r >> , now = ++cnt;
val[now] = a[mid], fa[now] = f, lazy[now] = ;
ch[now][] = build(l, mid - , now);
ch[now][] = build(mid + , r, now);
pushup(now);
return now;
}
int FindK(int root, int k) {
int now = root;
while () {
pushdown(now);
if (k <= siz[ch[now][]])
now = ch[now][];
else {
k -= siz[ch[now][]] + ;
if (k == )return now;
else now = ch[now][];
}
}
}
void rever(int l, int r) {
int ll = FindK(root, l);
int rr = FindK(root, r + );
splay(ll, );
splay(rr, ll);
pushdown(root);
lazy[ch[ch[root][]][]] ^= ;
}
void dfs(int x) {
pushdown(x);
if (ch[x][])dfs(ch[x][]);
if (val[x] != inf && val[x] != -inf)
printf("%d ", val[x]);
if (ch[x][])dfs(ch[x][]);
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++)
a[i + ] = i;
a[] = -inf, a[n + ] = inf;
root = build(, n + , );
while (m--) {
int l, r;
scanf("%d%d", &l, &r);
rever(l, r);
}
dfs(root);
}

无旋treap做法

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + ;
int Siz[maxn], ls[maxn], rs[maxn], pos[maxn], lazy[maxn], root;
int cnt;
inline void up(int x) {
Siz[x] = Siz[ls[x]] + Siz[rs[x]] + ;
}
inline void down(int x) {
if (lazy[x]) {
swap(ls[x], rs[x]);
lazy[ls[x]] ^= ;
lazy[rs[x]] ^= ;
lazy[x] = ;
}
}
void split_size(int x, int siz, int &A, int &B) {
if (x == )return (void)(A = B = );
down(x);
if (siz <= Siz[ls[x]])
B = x, split_size(ls[x], siz, A, ls[x]);
else
A = x, split_size(rs[x], siz - Siz[ls[x]] - , rs[x], B);
up(x);
}
int Merge(int A, int B) {
if (A == || B == )return A | B;
int ans;
down(A);
down(B);
if (pos[A] > pos[B])ans = A, rs[A] = Merge(rs[A], B);
else ans = B, ls[B] = Merge(A, ls[B]);
up(ans);
return ans;
}
int build(int l, int r) {
if (l > r)return ;
int mid = l + r >> ;
ls[mid] = build(l, mid - );
rs[mid] = build(mid + , r);
pos[mid] = rand();
up(mid);
return mid;
}
void dfs(int x) {
if (x) {
down(x);
dfs(ls[x]);
printf("%d ", x);
dfs(rs[x]);
}
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
root = build(, n);
while (m--) {
int l, r;
scanf("%d%d", &l, &r);
int A, B, C, D;
split_size(root, l - , A, B);
split_size(B, r - l + , C, D);
lazy[C] ^= ;
root = Merge(A, Merge(C, D));
}
dfs(root);
system("pause");
return ;
}

[Bzoj3223][Tyvj1729] 文艺平衡树(splay/无旋Treap)的更多相关文章

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

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

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

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

  3. [BZOJ3223] [Tyvj1729] 文艺平衡树 (splay)

    Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3  ...

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

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

  5. 2018.08.05 bzoj3223: Tyvj 1729 文艺平衡树(非旋treap)

    传送门 经典的平衡树问题,之前已经用splay写过一次了,今天我突发奇想,写了一发非旋treap的版本,发现挺好写的(虽然跑不过splay). 代码: #include<bits/stdc++. ...

  6. [模板] 平衡树: Splay, 非旋Treap, 替罪羊树

    简介 二叉搜索树, 可以维护一个集合/序列, 同时维护节点的 \(size\), 因此可以支持 insert(v), delete(v), kth(p,k), rank(v)等操作. 另外, prev ...

  7. [BZOJ3223/Tyvj1729]文艺平衡树

    Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列 其中需要提供以下操作: 翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 ...

  8. 浅谈无旋treap(fhq_treap)

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

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

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

随机推荐

  1. css盒子模型之边框宽度,边框颜色与边框样式

    /* width和height只是设置盒子内容区的大小,而不是盒子的整个大小, 盒子可见框的大小由内容区,内边距和边框共同决定. */ .box1 { /* 设置内容区的宽度为400px */ wid ...

  2. Spark 计算人员三度关系

    1.一度人脉:双方直接是好友 2.二度人脉:双方有一个以上共同的好友,这时朋友网可以计算出你们有几个共同的好友并且呈现数字给你.你们的关系是: 你->朋友->陌生人 3.三度人脉:即你朋友 ...

  3. MySQL第五天——日志

    日志 log_error(错误日志) 用于记录 MySQL 运行过程中的错误信息,如,无法加载 MySQL数据库的数据文件,或权限不正确等都会被记录在此. 默认情况下,错误日志是开启的,且无法禁止. ...

  4. Linux性能优化从入门到实战:01 Linux性能优化学习路线

      我通过阅读各种相关书籍,从操作系统原理.到 Linux内核,再到硬件驱动程序等等.   把观察到的性能问题跟系统原理关联起来,特别是把系统从应用程序.库函数.系统调用.再到内核和硬件等不同的层级贯 ...

  5. Linux性能优化从入门到实战:14 文件系统篇:Linux 文件系统基础

      磁盘为系统提供了最基本的持久化存储.   文件系统则在磁盘的基础上,提供了一个用来管理文件的树状结构. 文件系统:索引节点和目录项   文件系统是对存储设备上的文件,进行组织管理的机制.组织方式不 ...

  6. 启动模式:uefi, legacy,以及GRUB命令使用

    机器启动模式:uefi, legacy 设置入口:BIOS:boot mode 磁盘分区表格式: gpt uefi所使用(此种模式下,grub只能识别gpt格式的boot引导项) mbr legacy ...

  7. 对vueloader的研究

    vue-loader是webpack的加载器,允许您以称为单文件组件(SFC)的格式创作Vue组件: <template> <div class="example" ...

  8. XML 语法

    XML 语法规则 本节的目的是想让你了解 XML 中的语法所依据的规则,避免在编写 XML 文档的时候遇到错误. XML 的语法规则很简单,且很有逻辑.这些规则很容易学习,也很容易使用. 所有的 XM ...

  9. DELPHI 调试IOS时出现 Please specify exact device preset UUID

    右击设备DEVICE, 选择REFRESH刷新, 再重新选择一个设备即可.

  10. 阿里云推出SRT+杜比全景声直播方案,低成本打造高质量直播观感体验

    超过200个国家和地区共5144万人观看:浙江卫视.东方卫视55城总收视达2.39,稳居同时段市场第一:优酷直播间63%观看晚会的用户参与了互动:微博68.2亿的主话题阅读量:2019天猫双11狂欢夜 ...