题目描述

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

                --by洛谷

http://daniu.luogu.org/problem/show?pid=3391



裸的平衡树反转;

方法是按序列位置为关键字排序;

反转(l,r):

则将l-1置于根处,将r+1作为根的右儿子,这样,r+1的左子树就是需要反转的区间;

然后对r+1的左儿子,反转其左右儿子,并打上线段树一样的lazy标记,待以后反转她的子树;

一开始,企图把位置维护为关键字,然后排序;

这样,

若点A为父节点的左儿子,则key[A]=key[fa[A]]-size[rs[A]]-1;

若点A为父节点的右儿子,则key[A]=key[fa[A]]+size[ls[A]]+1;

然后查找直接按查询关键字的方法找,十分方便;

然而关键字是时时变化的,不好维护,

另一种方法是直接在初次建好树后就再也不考虑维护关键字的问题,

直接按第K大的方法搜索,(从某种意义上讲她早已不是一般意义上的查找树了)

怎么办,选哪种方法继续呢?

一个很好的方法是把两个都写出来,

反正差不多

多好啊,还能对拍,是吧

代码如下:

 #include<cstdio>
using namespace std;
int n,m;
struct dt{
int cnt,size,key,lz;
int ch[],fa;
};
struct Splay{
int root,tot;
dt data[];
void in(){
root=tot=;
data[].fa=data[].cnt=data[].size=data[].key=;
}
void splay(int x,int end){
int fa,fafa;
for(fa=data[x].fa;(fa=data[x].fa)!=end;roll(x)){
fafa=data[fa].fa;
if(fafa!=end){
if((data[fafa].ch[]==fa)^(data[fa].ch[]==x))
roll(x);
else
roll(fa);
}
}
if(!end)
root=x;
}
void roll(int x){
int fa=data[x].fa,fafa=data[fa].fa;
int wh=data[fa].ch[]==x;
data[fa].ch[wh]=data[x].ch[wh^];data[data[x].ch[wh^]].fa=fa;
data[x].ch[wh^]=fa;data[fa].fa=x;
if(fafa)
data[fafa].ch[data[fafa].ch[]==fa]=x;
data[x].fa=fafa;
up(fa);up(x);
}
void up(int x){
data[x].size=data[data[x].ch[]].size+data[data[x].ch[]].size+;
}
void buil_splay(int l,int r,int&nu,int fa){
int mid=(l+r)>>;
nu=++tot;
data[nu].key=mid;
data[nu].fa=fa;
data[nu].cnt=data[nu].size=;
if(l==r)return;
if(l<mid)
buil_splay(l,mid-,data[nu].ch[],nu);
if(r>mid)
buil_splay(mid+,r,data[nu].ch[],nu);
data[nu].size=data[data[nu].ch[]].size+data[data[nu].ch[]].size+;
}
int find(int x){
int i=root;
while(!(data[data[i].ch[]].size<x&&x<=data[i].size-data[data[i].ch[]].size)){
if(data[i].lz){
change(data[i].ch[]);
change(data[i].ch[]);
data[i].lz=;
}
if(x<=data[data[i].ch[]].size)
i=data[i].ch[];
else{
x-=(data[i].size-data[data[i].ch[]].size);
i=data[i].ch[];
}
}
if(data[i].lz){
change(data[i].ch[]);
change(data[i].ch[]);
data[i].lz=;
}
return i;
}
void change(int x){
int fa=data[x].fa,i;
i=data[x].ch[];data[x].ch[]=data[x].ch[];data[x].ch[]=i;
data[x].lz^=;
}
void print(int now){
if(data[now].lz){
change(data[now].ch[]);
change(data[now].ch[]);
data[now].lz=;
}
if(data[now].ch[])
print(data[now].ch[]);
if(data[now].key!=&&data[now].key!=n+)
printf("%d ",data[now].key);
if(data[now].ch[])
print(data[now].ch[]);
}
};
Splay splay;
int main()
{
int i,j,k,l;
scanf("%d%d",&n,&m);
splay.buil_splay(,n+,splay.root,);
for(i=;i<=m;i++){
scanf("%d%d",&j,&k);
if(j==k)continue;
l=splay.find(j);
splay.splay(l,);
l=splay.find(k+);
splay.splay(l,splay.root);
splay.change(splay.data[splay.data[splay.root].ch[]].ch[]);
}
splay.print(splay.root);
}

  

 #include<cstdio>
using namespace std;
int n,m;
struct dt{
int value,cnt,size,key,lz;
int ch[],fa;
};
struct Splay{
int root,tot;
dt data[];
void in(){
root=tot=;
data[].fa=data[].cnt=data[].size=data[].value=data[].key=;
}
void splay(int x,int end){
int fa,fafa;
for(fa=data[x].fa;(fa=data[x].fa)!=end;roll(x)){
fafa=data[fa].fa;
if(fafa!=end){
if((data[fafa].ch[]==fa)^(data[fa].ch[]==x))
roll(x);
else
roll(fa);
}
}
if(!end)
root=x;
}
void roll(int x){
int fa=data[x].fa,fafa=data[fa].fa;
int wh=data[fa].ch[]==x;
data[fa].ch[wh]=data[x].ch[wh^];data[data[x].ch[wh^]].fa=fa;
data[x].ch[wh^]=fa;data[fa].fa=x;
if(fafa)
data[fafa].ch[data[fafa].ch[]==fa]=x;
data[x].fa=fafa;
up(fa);up(x);
}
void up(int x){
data[x].size=data[data[x].ch[]].size+data[data[x].ch[]].size+;
}
void buil_splay(int l,int r,int&nu,int fa){
int mid=(l+r)>>;
nu=++tot;
data[nu].value=data[nu].key=mid;
data[nu].fa=fa;
data[nu].cnt=data[nu].size=;
if(l==r)return;
if(l<mid)
buil_splay(l,mid-,data[nu].ch[],nu);
if(r>mid)
buil_splay(mid+,r,data[nu].ch[],nu);
data[nu].size=data[data[nu].ch[]].size+data[data[nu].ch[]].size+;
}
int find(int x){
int i=root;
while(){
change(data[i].ch[]);
change(data[i].ch[]);
data[i].lz=;
if(data[i].value==x)
break;
i=data[i].ch[data[i].value<x];
}
return i;
}
void change(int x){
int fa=data[x].fa,i;
if(data[fa].lz){
i=data[x].ch[];data[x].ch[]=data[x].ch[];data[x].ch[]=i;
data[x].lz^=;
}
if(data[fa].ch[]==x)
data[x].value=data[fa].value-data[data[x].ch[]].size-;
else
data[x].value=data[fa].value+data[data[x].ch[]].size+;
}
void print(int now){
change(data[now].ch[]);
change(data[now].ch[]);
data[now].lz=;
if(data[now].ch[])
print(data[now].ch[]);
if(data[now].key!=&&data[now].key!=n+)
printf("%d ",data[now].key);
if(data[now].ch[])
print(data[now].ch[]);
}
};
Splay splay;
int main()
{
int i,j,k,l;
scanf("%d%d",&n,&m);
splay.buil_splay(,n+,splay.root,);
for(i=;i<=m;i++){
scanf("%d%d",&j,&k);
if(j==k)continue;
l=splay.find(j-);
splay.splay(l,);
l=splay.find(k+);
splay.splay(l,splay.root);
splay.data[splay.data[splay.root].ch[]].lz=;
splay.change(splay.data[splay.data[splay.root].ch[]].ch[]);
splay.data[splay.data[splay.root].ch[]].lz=;
}
splay.print(splay.root);
}

another_way

祝AC

洛谷 P3391 文艺平衡树的更多相关文章

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

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

  2. BZOJ3223/洛谷P3391 - 文艺平衡树

    BZOJ链接 洛谷链接 题意 模板题啦~2 代码 //文艺平衡树 #include <cstdio> #include <algorithm> using namespace ...

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

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

  4. 洛谷P3391 文艺平衡树 (Splay模板)

    模板题. 注意标记即可,另外,涉及区间翻转操作,记得设立首尾哨兵. 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int ...

  5. BZOJ3224/洛谷P3391 - 普通平衡树(Splay)

    BZOJ链接 洛谷链接 题意简述 模板题啦~ 代码 //普通平衡树(Splay) #include <cstdio> int const N=1e5+10; int rt,ndCnt; i ...

  6. 洛谷.3391.文艺平衡树(fhq Traep)

    题目链接 //注意反转时先分裂r,因为l,r是针对整棵树的排名 #include<cstdio> #include<cctype> #include<algorithm& ...

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

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

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

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

  9. [luogu P3391] 文艺平衡树

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

随机推荐

  1. React 初识

    React We built React to solve one problem: building large applications with data that changes over t ...

  2. 总结day04 ---- 列表的切片,增删改查,以及,相关方法, 元祖的使用方法

    内容大纲 1 : 列表的索引 : 列表的切片 2 : 列表的增加内容 >1:append(char)  >2:insert(index,char) >3:extend('可迭代对象' ...

  3. 【JS新手教程】浏览器弹出div层1

    JS中,可以弹出一个层来进行提示等作用,方法是利用css样式display样式,当display等于none时,该元素就不会在页面显示出来,而且元素也不会占空间.就是用户触发某些事件时,动态修改该样式 ...

  4. springcloud(五)-Ribbon

    前言 先发句牢骚,最近太TM忙了,一直没时间静下心来继续写微服务架构!EMMMMMM..... 经过前文的讲解,我们已经实现了微服务的注册与发现.启动各个微服务时,Eureka Client会把自己的 ...

  5. springboot(十二)-分布式锁(redis)

    什么是分布式锁? 要介绍分布式锁,首先要提到与分布式锁相对应的是线程锁.进程锁. 线程锁:主要用来给方法.代码块加锁.当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段.线程锁只在同一 ...

  6. SpringMVC初写(六)静态资源设置

    众所周知,SpringMVC的DispatchServlet是不可以以/*规则拦截请求的,否则会将JSP都拦截了,但有时候我们的请求路径是不能有后缀(Resful风格的接口需要),基于上述情况,我们可 ...

  7. EJB与JavaBean

    JavaBean是一个组件,而EJB就是一个组建框架.JavaBean面向的是业务逻辑和表示层的显示,通过编写一个JavaBean,可以将业务逻辑的事件和事务都放在其中,然后通过它的变量属性将所需要的 ...

  8. 设计模式--策略模式(strategy)

    1.策略模式(strategy ['strætədʒi]) 我的理解是:方案候选模式 (反正关键就是有很多的候选,哈哈) 看了很多例子,都是在说鸭子的,那个例子很好,在这里可以看 他们生产鸭子,我们就 ...

  9. CSS position属性absolute relative等五个值的解释

    DIV CSS position绝对定位absolute relative教程篇 常常使用position用于层的绝对定位,比如我们让一个层位于一个层内具体什么位置,为即可使用position:abs ...

  10. 哪些网站需要HTTPS(SSL证书)

    很多站长似乎不了解https站点是怎么回事,这就要从传统站点说起:传统的站点的http超文本传输协议,采用明文传输模式,存在着大量的灰色中 间环节,明文信息在中间代理服务器.路由器.wifi热点.通信 ...