题目大意:给定一个$1\sim n$的序列,每次翻转一个区间,输出最后的序列。

解题思路:Splay的区间翻转操作。我借此打了个Splay的模板(运用内存池,但有些功能不确定正确,例如单点插入)。

大致思路就是,每次找到$l−1$和$r+1$两个节点,把$l−1$旋转到根,$r+1$旋转到根的右子树,则根的右子树的左子树就是$l,r$的区间。

对于翻转一个区间,直接打上标记,访问到这个节点时,下传标记并交换两个儿子节点。

注意访问$l−1$,$r+1$时可能访问到$0$和$n+1$,所以要多开两个节点。

最后输出即可。

C++ Code:

#include<bits/stdc++.h>
inline int readint(){
char c=getchar();
for(;!isdigit(c);c=getchar());
int d=0;
for(;isdigit(c);c=getchar())
d=(d<<3)+(d<<1)+(c^'0');
return d;
}
int n;
template<typename T>
class Splay{
private:
struct node{
T value;
int sz;
bool rotag;
node *fa,*ch[2];
};
public:
node* rt;
int n;
private:
node a[1000000],*stk[1000000];
int top;
inline void pushdown(node* t){
if(t->rotag){
node* x=t->ch[0];
t->ch[0]=t->ch[1];
t->ch[1]=x;
if(t->ch[0]!=NULL)
t->ch[0]->rotag^=1;
if(t->ch[1]!=NULL)
t->ch[1]->rotag^=1;
t->rotag=0;
}
}
inline node* newnode(T v,node* f){
node* now=stk[--top];
now->sz=1;
now->value=v;
now->fa=f;
now->ch[0]=now->ch[1]=NULL;
now->rotag=false;
return now;
}
inline void dispose(node*&t){stk[top++]=t;t=NULL;}
inline int findson(node* f,node* s){
return(f->ch[1]==s)?1:0;
}
inline void update(node* t){
t->sz=1;
if(t->ch[0]!=NULL)t->sz+=t->ch[0]->sz;
if(t->ch[1]!=NULL)t->sz+=t->ch[1]->sz;
}
inline void rotate(node* t){
node* f=t->fa;
node* g=f->fa;
int a=findson(f,t),b=a^1;
if(t->ch[b]!=NULL)t->ch[b]->fa=f;
f->ch[a]=t->ch[b];
t->ch[b]=f;
f->fa=t;
t->fa=g;
if(g!=NULL)g->ch[findson(g,f)]=t;else
rt=t;
update(f);
update(t);
}
public:
Splay(){
for(int i=0;i<1000000;++i)stk[i]=&a[i];
top=1000000;
}
inline void splay(node* t,node* p){
if(t==NULL)return;
pushdown(t);
while(t->fa!=p){
node* f=t->fa;
node* g=f->fa;
if(g==p)rotate(t);else
if(findson(g,f)!=findson(f,t))
rotate(t),rotate(t);else
rotate(f),rotate(t);
}
}
inline node* find(node* now,int y){
while(now!=NULL){
pushdown(now);
int t;
if(now->ch[0]==NULL)t=1;else
t=now->ch[0]->sz+1;
if(t==y)return now;
if(t<y)y-=t,now=now->ch[1];else
now=now->ch[0];
}
}
inline void build(node*& p,int l,int r,node* f=NULL){
if(l>r)return;
int mid=l+r>>1;
p=newnode(mid,f);
build(p->ch[0],l,mid-1,p);
build(p->ch[1],mid+1,r,p);
update(p);
}
inline void insert(T val){
if(rt==NULL)rt=newnode(val,NULL);
int x;
for(node* t=rt;t;t=t->son[x]){
x=val>=t->value?1:0;
if(t->ch[x]==NULL){t->son[x]=newnode(val,t);splay(t->son[x],rt);break;}
}
}
inline void rev(node* p,int l,int r){
node* pre=find(p,l),*suc=find(p,r);
splay(pre,NULL);
splay(suc,rt);
if(rt->ch[1]->ch[0]!=NULL)
rt->ch[1]->ch[0]->rotag^=1;
}
inline void print(node* p){
if(p==NULL)return;
pushdown(p);
print(p->ch[0]);
if(p->value>1&&p->value<n+2)printf("%d ",p->value-1);
print(p->ch[1]);
}
inline void build(int nn){
n=nn;
build(rt,1,n+2);
}
};
Splay<int>Tree;
int main(){
n=readint();int m=readint();
Tree.build(n);
while(m--){
int l=readint(),r=readint();
Tree.rev(Tree.rt,l,r+2);
}
Tree.print(Tree.rt);
return 0;
}

[洛谷P3391]【模板】文艺平衡树(Splay)的更多相关文章

  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. luoguP3391[模板]文艺平衡树(Splay) 题解

    链接一下题目:luoguP3391[模板]文艺平衡树(Splay) 平衡树解析 这里的Splay维护的显然不再是权值排序 现在按照的是序列中的编号排序(不过在这道题目里面就是权值诶...) 那么,继续 ...

  5. 洛谷 P3391 模板Splay

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

  6. 【洛谷P3369】普通平衡树——Splay学习笔记(一)

    二叉搜索树(二叉排序树) 概念:一棵树,若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 它的左.右子树也分别为二叉搜索树 ...

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

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

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

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

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

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

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

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

随机推荐

  1. 训练1-J

    把一个偶数拆成两个不同素数的和,有几种拆法呢? Input 输入包含一些正的偶数,其值不会超过10000,个数不会超过500,若遇0,则结束. Output 对应每个偶数,输出其拆成不同素数的个数,每 ...

  2. BZOJ 2161 布娃娃 (主席树)

    题面 想了一个主席树做法 我们把每个区间的两个端点拆开 对$L,R$分别从小到大排序,分别从左到右依次把对应标号的$c_{i}$插入到权值主席树里 每次查询$p_{i}$,在排序后的$L,R$数组上分 ...

  3. 终极对决!Dubbo 和 Spring Cloud 微服务架构到底孰优孰劣

    标签: 微服务dubbospring架构 前言 微服务架构是互联网很热门的话题,是互联网技术发展的必然结果.它提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值.虽然 ...

  4. 探索Python的多态是怎么实现的

    多态是指通过基类的指针或者引用,在运行时动态调用实际绑定对象函数的行为. 对于其他如C++的语言,多态是通过在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来 ...

  5. 【hiho一下 第八周】状态压缩·一

    [题目链接]:http://hihocoder.com/problemset/problem/1044 [题意] [题解] 设f[i][j]表示; 前i-1个位置已经决策完; 然后i-m+1..i这一 ...

  6. GROUP BY 和 ORDER BY 的一起使用

    GROUP BY 和 ORDER BY一起使用 写程序也有很长的一段时间了,有些东西我总不曾去思考,很少去积累一些有用的东西,总喜欢"用要即拿"的心态来对待,这是非常不好的坏习惯. ...

  7. [JAVA]比毫秒System.currentTimeMillis()更精确的时间戳(纳米级时间戳)

     纳秒 ns(nanosecond):纳秒, 时间单位.一秒的10亿分之中的一个,即等于10的负9次方秒. 经常使用作 内存读写速度的单位,其前面数字越小则表示速度越快. 1纳秒=1000 皮秒 ...

  8. 定时任务为什么不用Timer

    在做定时任务的时候,有的同学可能能会用到Timer这个定时任务的辅助类, 可是使用它会有潜在的风险,风险例如以下, (1)时间计算不准确问题     由于Timer是以绝对时间计算定时任务的,会受到系 ...

  9. 经验之谈—OAuth授权流程图

    事实上我们在开发中,常常须要解决获得用户的一些特定的数据,比方:能够选择使用微博登陆.使用QQ登陆等等.然后我们间接的获得用户的头像.昵称等信息.这些都涉及到OAuth授权的内容 OAuth授权有这么 ...

  10. PDF转EPUB格式电子书经验总结

    依据本人将PDF转换为EPUB电子书的经验,总结整理了这篇文章.因本人水平有限,难免有错误和不足之处,望大家及时批评指正.   写这篇文章时,假定读者已经会使用文中所列出软件的基本操作,比方如何用No ...