[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 您需要写一种数据结构(可参考题目标题),来维护一个 ...
随机推荐
- C# 获得系统环境
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- Spring Data Elasticsearch 用户指南
https://www.jianshu.com/p/27e1d583aafb 翻译自官方文档英文版,有删减. BioMed Central Development Team version 2.1.3 ...
- 了解Greenplum (2)
一.目的 1. 理解Greenplum中的数据分布策略(random 和 distribution),分析不同分布策略的优劣:2. 理解查询执行中的数据广播和数据重分布,分析在何种情况下选择哪种策略, ...
- python基础--4 元祖
#元组,元素不可被修改,不能被增加或者删除 #tuple,有序 tu=(11,22,33,44,55,33) #count 获取指定元素在元祖中出现的次数 print(tu.count(33)) #i ...
- HTML5 音频播放
代码实例: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...
- 22.Express框架——2019年12月19日
2019年12月19日14:16:36 1. express简介 1.1 介绍 Express框架是后台的Node框架,所以和jQuery.zepto.yui.bootstrap都不一个东西. Exp ...
- sed 搜索并替换
find . -type f -exec sed -i "s/std=c++11/std=c++14/g" {} \; 搜索当前目录下的文件,把std=c++11替换成std=c+ ...
- Cobaltstrike系列教程(三)-beacon详解
0x000--前文 Cobaltstrike系列教程(一)-简介与安装 Cobaltstrike系列教程(二)-Listner与Payload生成 heatlevel 0x001-Beacon详解 1 ...
- maven推送本地包到私服
前置要求:配置正确的settings.xml maven 推送 本地jar 到私服的命令示例: mvn deploy:deploy-file -DgroupId=com.oracle -Dartifa ...
- Linux学习-基于CentOS7的MySQL5.7的GTID复制
一.GTID复制简介 GTID (global transaction id)全局事务标识符,MySQL5.6版本开始支持,GTID复制不像传统的复制方式(导步复制.半同步复制)需要找到binlog和 ...