题目背景

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

题目描述

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

输入输出格式

输入格式:

第一行为n,m(n,m<=100000) 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次变换后的结果

输入输出样例

输入样例

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

4 3 2 1 5

splay模板题,维护该序列的中序遍历不变,然后每次通过旋转节点使操作的区间变作一颗字树,然后打上标记即可。
什么是splay?
一棵伸展树......
什么是伸展树?
最近刚学,我个人的理解,大概就是一个能在不破坏二叉搜索树结构(即中序遍历始终为升序)的情况下
通过旋转一个节点到他根节点位置使得操作区间恰好全部位于一棵子树内的方法。 然后就打上标记,之后在类似线段树一样的pushdown传递信息就好了。 代码如下:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define mod
#define mid (R+L>>1)
#define M 2000010
using namespace std;
LL read(){
LL nm=,oe=;char cw=getchar();
while(!isdigit(cw)) oe=cw=='-'?-oe:oe,cw=getchar();
while(isdigit(cw)) nm=nm*+(cw-''),cw=getchar();
return nm*oe;
}
LL n,m,l[M],r[M],tp[M],ad,sz[M],tg[M],ace,a,b,p,q,cnt;
bool flag=false;
void pushdown(LL x){
if(tg[x]==) return;
tg[x]=,swap(l[x],r[x]);
tg[l[x]]^=,tg[r[x]]^=;
}
void pushup(LL x){sz[x]=sz[l[x]]+sz[r[x]]+;}
LL build(LL L,LL R,LL rt){
if(L>R) return ;
tp[mid]=rt,sz[mid]=;
if(L==R) return L;
l[mid]=build(L,mid-,mid);
r[mid]=build(mid+,R,mid);
sz[mid]+=sz[l[mid]]+sz[r[mid]];
return mid;
}
void rotate(LL x){
if(ace==x) return;
LL top=tp[x];
pushdown(top),pushdown(x);
if(top==ace) ace=x,tp[x]=n+,tp[top]=x;
else{
if(l[tp[top]]==top) l[tp[top]]=x;
else r[tp[top]]=x;
tp[x]=tp[top],tp[top]=x;
}
if(l[top]==x) l[top]=r[x],tp[r[x]]=top,r[x]=top;
else r[top]=l[x],tp[l[x]]=top,l[x]=top;
pushup(top),pushup(x);
}
void oper(LL x){
if(x==ace||tp[x]==ace){return;}
LL top=tp[x];
pushdown(top);
if(tp[top]==ace) rotate(x);
else if(l[l[tp[top]]]==x||r[r[tp[top]]]==x) rotate(top);
else rotate(x);
}
LL find(LL x,LL pos){
pushdown(x);
if(sz[l[x]]==pos-) return x;
if(sz[l[x]]<pos-) return find(r[x],pos-sz[l[x]]-);
else return find(l[x],pos);
}
void ans(LL x){
if(x==) return;
pushdown(x);
ans(l[x]);
if(x<n&&x>){
if(flag) printf(" ");
flag=true;
printf("%lld",x-);
}
ans(r[x]);
}
int main(){
n=read()+,m=read(),ace=build(,n,n+);
while(m--){
a=read(),b=read();
p=find(ace,a),q=find(ace,b+);
while(tp[q]!=ace&&q!=ace) oper(q);
if(q!=ace) rotate(q);
while(tp[p]!=ace) oper(p);
tg[r[p]]^=;
}
ans(ace);
return ;
}

我这里还是写的比较模糊,我也是通过了解别人的博客才理解了splay

就是这个 -> http://blog.csdn.net/skydec/article/details/20151805

洛谷 P3391 【模板】文艺平衡树的更多相关文章

  1. 洛谷.3391.[模板]文艺平衡树(Splay)

    题目链接 //注意建树 #include<cstdio> #include<algorithm> const int N=1e5+5; //using std::swap; i ...

  2. 【洛谷P3391】文艺平衡树——Splay学习笔记(二)

    题目链接 Splay基础操作 \(Splay\)上的区间翻转 首先,这里的\(Splay\)维护的是一个序列的顺序,每个结点即为序列中的一个数,序列的顺序即为\(Splay\)的中序遍历 那么如何实现 ...

  3. 洛谷.3369.[模板]普通平衡树(Splay)

    题目链接 第一次写(2017.11.7): #include<cstdio> #include<cctype> using namespace std; const int N ...

  4. 洛谷.3369.[模板]普通平衡树(fhq Treap)

    题目链接 第一次(2017.12.24): #include<cstdio> #include<cctype> #include<algorithm> //#def ...

  5. 洛谷 P3391 模板Splay

    #include<bits/stdc++.h> using namespace std; #define maxn 200000 int read() { ,w=; ;ch=getchar ...

  6. 洛谷 P3391 【模板】文艺平衡树(Splay)

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

  7. 【阶梯报告】洛谷P3391【模板】文艺平衡树 splay

    [阶梯报告]洛谷P3391[模板]文艺平衡树 splay 题目链接在这里[链接](https://www.luogu.org/problemnew/show/P3391)最近在学习splay,终于做对 ...

  8. [洛谷P3391] 文艺平衡树 (Splay模板)

    初识splay 学splay有一段时间了,一直没写...... 本题是splay模板题,维护一个1~n的序列,支持区间翻转(比如1 2 3 4 5 6变成1 2 3 6 5 4),最后输出结果序列. ...

  9. 洛谷P3391文艺平衡树(Splay)

    题目传送门 转载自https://www.cnblogs.com/yousiki/p/6147455.html,转载请注明出处 经典引文 空间效率:O(n) 时间效率:O(log n)插入.查找.删除 ...

  10. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

随机推荐

  1. iOS的异步绘制--YYAsyncLayer源码分析

    iOS的异步渲染 最近看了YYAsyncLayer在这里总结一下.YYAsyncLayer是整个YYKit异步渲染的基础.整个项目的Github地址在这里.你可以先下载了一睹为快,也可以跟着我一步一步 ...

  2. Collection和Map的默认扩容参数

    初始大小:调用无参构造函数时默认的容量 加载因子:超过 (当前容量*加载因子) 时会进行扩容 扩容因子:扩容时增加的容量为 (当前容量*扩容因子)        容器         初始容量    ...

  3. Re-Order Buffer

    Re-order Buffer(ROB)是处理器中非常重要的一个模块,它位于renamer与scheduler(RS)之间,并且也是execution unit(EU)的出口.ROB作为指令处理的后端 ...

  4. 每天十分钟系列:JS数据操作之神奇的map()

    Array.prototype.map() map()方法可以创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果. demo1 上面的例子,在控制台中打印的结果是: 1 2 3 ...

  5. CoreCLR源码探索(七) JIT的工作原理(入门篇)

    很多C#的初学者都会有这么一个疑问, .Net程序代码是如何被机器加载执行的? 最简单的解答是, C#会通过编译器(CodeDom, Roslyn)编译成IL代码, 然后CLR(.Net Framew ...

  6. C# 动态加载卸载 DLL

    我最近做的软件,需要检测dll或exe是否混淆,需要反射获得类名,这时发现,C#可以加载DLL,但不能卸载DLL.于是在网上找到一个方法,可以动态加载DLL,不使用时可以卸载. 我在写一个WPF 程序 ...

  7. (@WhiteTaken)设计模式学习——组合模式

    下面来学习一下组合模式. 组合模式概念是什么呢.从别的地方抄来了一些理论. 理论:将对象组合成树形结构以表示"部分-整体"的层次结构.Composite模式使得用户对单个对象和组合 ...

  8. Bootstrap 引用的标准模板

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...

  9. mybatis mysql 批量插入

    场景描述: 使用mybatis操作mysql数据库,进行批量插入数据,提高代码质量和执行效率. 环境: mybatis spring mysql java xml配置文件 <insert id ...

  10. Linux.根据进程名关键字杀进程

    先看例子, 假设系统中有以下2个进程 USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND root     ...