题目链接: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样式给表格tbody加垂直滚动条

    tbody加滚动条实现思路: 1,把tbody设置成display:block,然后就对其高度设置一个固定值,overflow设置成auto. 2,把thead的tr设置成display:block. ...

  2. Xshell设置密钥登录确保Linux

    用Xshell设置密匙登陆服务器, 第一步.使用Xshell生成密钥 我们打开熟悉的XSHELL软件,然后在工具-新建用户密钥生成向导. 到了生成密钥参数界面,我们这里需要选择RSA密钥类型,以及密钥 ...

  3. TensorFlow学习笔记2:逻辑回归实现手写字符识别

    代码比较简单,没啥好说的,就做个记录而已.大致就是现建立graph,再通过session运行即可.需要注意的就是Variable要先初始化再使用. import tensorflow as tf fr ...

  4. eclipse 代码提示快捷键 alt+/

    eclipse (ALT+/)1.选择Eclipse菜单栏中的Window->preferences: 2.选择General->keys; 3.在右侧中间的窗体中点击word compl ...

  5. 2018-10-25-weekly

    Algorithm 94. 二叉树的中序遍历 What 给定一个二叉树,返回它的中序遍历. How 二叉树的中序遍历顺序为左-根-右,可以用递归来解,对左子结点调用递归函数,根节点访问值,右子节点再调 ...

  6. DispatcherServlet的工作原理

    下面是DispatcherServlet的工作原理图,图片来源于网络. 下面是我从DispatcherServlet源码层面来分析其工作流程: 1.请求到达后,调用HandlerMapping来查找对 ...

  7. Task2.设立计算图并自动计算

    1.numpy和pytorch实现梯度下降法 import numpy as np # N is batch size; N, D_in, H, D_out = 64, 1000, 100, 10 # ...

  8. JavaScript中数组的操作方法总汇

    Array(数组)是JavaScript中最为常用的类型了.ECMAScript中的数组都是数据的有序列表.数组中可以保存任何类型的数据.数组的大小是可以动态调整的,既可以随着数据的添加自动增长以容纳 ...

  9. tensorflow2 矩阵乘法问题

    tensorflow2再做矩阵相乘的时候如果维度有None,则矩阵相乘结果不对. 也不知道为什么,只能用矩阵对应元素相乘在相加的形式来实现矩阵相乘,这个困扰了我好几天,所以记下来. inputs_ti ...

  10. 图论 List

    题目 #A 小 K 的农场 (Unaccepted)    #B 信息传递 (Unaccepted)    #C 最短路计数 (Accepted)    #D 通往奥格瑞玛的道路 (Accepted) ...