http://www.lydsy.com/JudgeOnline/problem.php?id=3223

题面复制于洛谷。

题目背景

这是一道经典的Splay模板题——文艺平衡树。

题目描述

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

输入输出格式

输入格式:

第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2, \cdots n-1,n)(1,2,⋯n−1,n) m表示翻转操作次数

接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r \leq n1≤l≤r≤n

输出格式:

输出一行n个数字,表示原始序列经过m次变换后的结果

输入输出样例

输入样例#1:

5 3
1 3
1 3
1 4
输出样例#1:

4 3 2 1 5

说明

N,M<=100000

——————————————————————————————————

这里就要用到splay翻转区间的操作了。

我们首先考虑,假设我们翻转整个区间的话,那十分的好办——以根节点为对称轴将其他点全都“对称”过去即可。

比如原图如下

我们变成

这显然是正确的。

该操作可以简述为:交换当前结点的左右儿子,递归左右儿子。

考虑当我们要翻转部分区间的时候,我们这么做显然不对。

但是通过类比的思路,我们能够猜想如果我们对其中一个子树进行如此操作的话是不是就可以了。

那么我们就需要试图找到如此变形后的树:我们要翻转的区间必须全部在一个结点的左儿子侧,且左儿子侧不能有其他多余的点。

为什么这么做呢?思考我们有一个长度为4的区间1 2 3 4,现在要翻转2-3的区间,即变成1 3 2 4

当我们的树变成这样的时候:

我们以3为对称轴翻转操作得到:

显然我们得到了正确的结果。

所以我们发现当我们要翻转[l,r]的时候,我们只需要通过splay将l-1的点放在root,r+1放在root的儿子处即可。

那么就有一个问题了,假设我们要翻转1-3区间时怎么办?l-1=0,可是我们没有这样的点怎么办?

我们人为添加不就行了?

所以我们加入0结点和n+1结点,这样就可以查询了。

(但是0在splay有很重要的意义,所以本代码将所有的编号往后移动一位)

但是这样的优化远远不够:思考进行了连续多次的修改区间的操作,我们发现后一次修改可能覆盖掉前一次修改,而翻转*2=不翻转,所以我们有了lazy延迟的想法。

我们对于要交换左右儿子的结点打上lazy标记,同时在更新的时候下传即可。

#include<cstdio>
#include<queue>
#include<cctype>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
const int N=;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
int fa[N],tr[N][],key[N],size[N];
int root,sz;
bool lazy[N];
inline bool get(int x){
return tr[fa[x]][]==x;
}
inline void update(int x){
if(x){
size[x]=;
if(tr[x][])size[x]+=size[tr[x][]];
if(tr[x][])size[x]+=size[tr[x][]];
}
return;
}
inline void rotate(int x){
int old=fa[x],oldf=fa[old],which=get(x);
tr[old][which]=tr[x][which^];fa[tr[old][which]]=old;
fa[old]=x;tr[x][which^]=old;fa[x]=oldf;
if(oldf)tr[oldf][tr[oldf][]==old]=x;
update(old);update(x);
return;
}
inline void splay(int x,int y){
int f=fa[x];
while(f!=y){
if(fa[f]!=y)rotate((get(x)==get(f)?f:x));
rotate(x);f=fa[x];
}
if(!y)root=x;
return;
}
inline void insert(int v){
sz++;tr[sz][]=tr[sz][]=fa[sz]=;
key[sz]=v;size[sz]=;
if(sz==)root=sz;
else{
tr[sz-][]=sz;
fa[sz]=sz-;
update(fa[sz]);splay(sz,);
}
return;
}
inline void pushdown(int x){
if(!lazy[x])return;
swap(tr[x][],tr[x][]);
lazy[tr[x][]]^=;
lazy[tr[x][]]^=;
lazy[x]=;
return;
}
inline int kthmin(int k,int x){
pushdown(x);
if(k==+size[tr[x][]])return x;
else if(k<=size[tr[x][]])return kthmin(k,tr[x][]);
else return kthmin(k-size[tr[x][]]-,tr[x][]);
}
inline void turn(int l,int r){
int x=kthmin(l-,root);
int y=kthmin(r+,root);
splay(x,);splay(y,x);
lazy[tr[y][]]^=;
return;
}
int main(){
int n=read();
int m=read();
for(int i=;i<=n+;i++)insert(i+);
for(int i=;i<=m;i++){
int l=read()+;
int r=read()+;
turn(l,r);
}
for(int i=;i<=n+;i++)printf("%d ",key[kthmin(i,root)]-);
return ;
}

BZOJ3223:文艺平衡树——超详细题解的更多相关文章

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

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

  2. BZOJ3223 文艺平衡树(splay)

    题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1, ...

  3. bzoj3223 文艺平衡树 (treap or splay分裂+合并)

    3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 3313  Solved: 1883 [Submit][S ...

  4. BZOJ3223文艺平衡树——非旋转treap

    此为平衡树系列第二道:文艺平衡树您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作: 翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 ...

  5. JZYZOJ1998 [bzoj3223] 文艺平衡树 splay 平衡树

    http://172.20.6.3/Problem_Show.asp?id=1998 平衡树区间翻转的板子,重新写一遍,给自己码一个板子. #include<iostream> #incl ...

  6. [bzoj3223]文艺平衡树——splay

    题意 你应当编写一个数据结构,支持以下操作: 反转一个区间 题解 我们把在数组中的位置当作权值,这样原序列就在这种权值意义下有序,我们考虑使用splay维护. 对于操作rev[l,r],我们首先把l- ...

  7. bzoj3223 文艺平衡树

    传送门 :http://www.lydsy.com/JudgeOnline/problem.php?id=3223 splay区间翻转的基础题,然而我还是调了一晚上(蒟蒻的悲哀) #include & ...

  8. [luogu3391][bzoj3223]文艺平衡树【splay】

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

  9. [bzoj3223]文艺平衡树(splay区间反转模板)

    解题关键:splay模板题. #include<cstdio> #include<cstring> #include<algorithm> #include< ...

随机推荐

  1. 翻译:利用GDAL生成cogeoff文件

    翻译自: Introducing the AWS Lambda Tiler https://hi.stamen.com/stamen-aws-lambda-tiler-blog-post-76fc11 ...

  2. 苏醒的巨人----CSRF

    一.CSRF 跨站请求伪造(Cross-Site Request Forgery,CSRF)是指利用 受害者尚未失效的身份认证信息(cookie.会话等),诱骗其点 击恶意链接或者访问包含攻击代码的页 ...

  3. 用Anko和Kotlin实现Android上的对话框和警告提示(KAD 24)

    作者:Antonio Leiva 时间:Mar 9, 2017 原文链接:https://antonioleiva.com/dialogs-android-anko-kotlin/ 借助Builder ...

  4. GIt学习第一天之安装和版本库创建

    搬运自 ‘廖雪峰的官方网站’ 1.git安装 官网下载地址:https://git-scm.com/download/win   百度网盘下载地址:https://pan.baidu.com/s/1k ...

  5. 【Extremely Basic Words for Listening】word list

    [Extremely Basic Words for Listening]word list updated continuously recite count: 0 careless exercis ...

  6. Java and SDK 环境变量设置

    File comes from http://www.cnblogs.com/shinge/p/5500002.html JAVA环境变量配置详解 JAVA环境变量JAVA_HOME.CLASSPAT ...

  7. 8月leetcode刷题总结

    刷题链接:https://leetcode-cn.com/explore/ 根据leetcode的探索栏目,八月份一直在上面进行刷题.发现算法题真的好难,真-计算机思维. 核心是将现实问题转化为计算机 ...

  8. lintcode 二叉树中序遍历

    /** * Definition of TreeNode: * class TreeNode { * public: * int val; * TreeNode *left, *right; * Tr ...

  9. 洛谷 P1781 宇宙总统:sort(string)

    题目描述 地球历公元6036年,全宇宙准备竞选一个最贤能的人当总统,共有n个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统. 输入输出格式 输入格式: 第一行为一个整数n,代表竞选 ...

  10. leetcode个人题解——#20 Valid Parentheses

    class Solution { public: bool isValid(string s) { stack<char> brackts; ; i < s.size(); i++) ...