[Bzoj3223][Tyvj1729] 文艺平衡树(splay/无旋Treap)
题目链接: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)的更多相关文章
- BZOJ - 3223 Tyvj 1729 文艺平衡树 (splay/无旋treap)
题目链接 splay: #include<bits/stdc++.h> using namespace std; typedef long long ll; ,inf=0x3f3f3f3f ...
- [Bzoj3224][Tyvj1728] 普通平衡树(splay/无旋Treap)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3224 平衡树入门题,学习学习. splay(学习yyb巨佬) #include<b ...
- [BZOJ3223] [Tyvj1729] 文艺平衡树 (splay)
Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 ...
- 【序列操作V】平衡树(无旋treap)
题目描述 维护一个队列,初始为空.依次加入 n(1≤n≤105)个数 ai(-109≤ai≤109),第 i(1≤i≤n)个数加入到当前序列第 bi(0≤bi≤当前序列长度)个数后面.输出最终队列. ...
- 2018.08.05 bzoj3223: Tyvj 1729 文艺平衡树(非旋treap)
传送门 经典的平衡树问题,之前已经用splay写过一次了,今天我突发奇想,写了一发非旋treap的版本,发现挺好写的(虽然跑不过splay). 代码: #include<bits/stdc++. ...
- [模板] 平衡树: Splay, 非旋Treap, 替罪羊树
简介 二叉搜索树, 可以维护一个集合/序列, 同时维护节点的 \(size\), 因此可以支持 insert(v), delete(v), kth(p,k), rank(v)等操作. 另外, prev ...
- [BZOJ3223/Tyvj1729]文艺平衡树
Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列 其中需要提供以下操作: 翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 ...
- 浅谈无旋treap(fhq_treap)
一.简介 无旋Treap(fhq_treap),是一种不用旋转的treap,其代码复杂度不高,应用范围广(能代替普通treap和splay的所有功能),是一种极其强大的平衡树. 无旋Treap是一个叫 ...
- [BZOJ3223]文艺平衡树 无旋Treap
3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec Memory Limit: 128 MB Description 您需要写一种数据结构(可参考题目标题),来维护一个 ...
随机推荐
- HashMap、Hashtable和ConcurrentHashMap的区别
HashTable 底层数组+链表实现,无论key还是value都不能为null,线程安全,实现线程安全的方式是在修改数据时锁住整个HashTable,效率低,ConcurrentHashMap做了相 ...
- Linux--shell三剑客<sed>--07
1.sed(stream editor): 作为行编辑器,对文本进行编辑(以行为单位) 默认显示输出所有文件内容 注意:sed编辑文件,却不改变原文件 2.sed的工作原理: 指定一个文本文件,依次读 ...
- KC705E 增强版 基于FMC接口的Xilinx Kintex-7 FPGA K7 XC7K325T PCIeX8 接口卡
KC705E 增强版 基于FMC接口的Xilinx Kintex-7 FPGA K7 XC7K325T PCIeX8 接口卡 一.板卡概述 本板卡基于Xilinx公司的FPGAXC7K325T-2FF ...
- openGL图形渲染管线
在OpenGL中,任何事物都在3D空间中,而屏幕和窗口却是2D像素数组,这导致OpenGL的大部分工作都是关于把3D坐标转变为适应屏幕的2D像素.3D坐标转为2D坐标的处理过程是由OpenGL的图形渲 ...
- bzoj2402 陶陶的难题II 分数规划+树剖+线段树维护凸壳+二分
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=2402 题解 看上去很像分数规划的模型.于是就二分吧.令 \[ \begin{align*}\f ...
- Linux学习-MySQL的主从复制高可用性解决方案MHA
一.MHA简介 1.MHA Master High Availability,对主节点进行监控,可实现自动故障转移至其它从节点:通过提升某一从节点为新的主节点,基于主从复制实现,还需要客户端配合实现, ...
- redis学习 --List
1:添加 lpush rpush 如果没有key的话,会报错. lpushx rpushx 如果没有key的话,不做任何反应. 2:得到 lpop rpop ...
- asp.net文件断点上传
HTML部分 <%@PageLanguage="C#"AutoEventWireup="true"CodeBehind="index.aspx. ...
- [CF846E]Chemistry in Berland题解
这题乍一看是一道水树形DP(其实事实上它确实是树形DP),然后设f[i]表示第i个点所多余/需要的材料,然后我们愉快的列出了式子: if(f[v]<0) f[u] += f[v] * edges ...
- 【Java】java.sql.SQLDataException: Cannot determine value type from string
报错如下: There was an unexpected error (type=Internal Server Error, status=500). Error attempting to ge ...