前言
在學習這一節之前顯然要先會非旋Treap的基本操作
Split和Merge
S
p
l
i
t
和
M
e
r
g
e
就可以了
正題
首先,我們用Treap的中序遍曆來代表現在的數列
顯然翻轉區間相當於交換子樹
同時值得注意的是堆的性質不會影響到樹的中序遍曆(這個自己要想一想)
我們在之前強調
Merge(a,b)
M
e
r
g
e
(
a
,
b
)
的大小問題,在這裡只要按照原來樹的順序搞就行了,他已經不是搜索二叉樹了,維持形態即可
翻轉需要rev的懶惰標記
Split,Merge
S
p
l
i
t
,
M
e
r
g
e
時要下推,否則之後的操作就錯了,因為作用區間錯了
沒什麼可說了直接看代碼
#include<cstdio>
#include<iostream>
using namespace std;
inline void read(int &x)
{
int s=0,w=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')w=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
s=(s<<3)+(s<<1)+c-'0';
c=getchar();
}
x=s*w;
}
inline void write(int x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar('0'+x%10);
}
template<class a,class b>class Pair
{
public:
a first;
b second;
Pair(a x,b y){first=x,second=y;}
Pair(){}
};
int seed=2333;
inline int Random(){return seed=seed*seed+seed;}
struct node
{
int val,key,size;
node *son[2];
bool rev;
node(const int &x);
inline void push_up(){size=son[0]->size+son[1]->size+1;}
inline void push_down();
}*nil=new node(0),*Root;
node::node(const int &x)
{
val=x,key=Random(),size=1,son[0]=son[1]=nil,rev=false;
}
inline void node::push_down()
{
if(!rev)return ;
son[0]->rev^=1,son[1]->rev^=1;
rev=0;
swap(son[0],son[1]);
}
Pair<node*,node*>split(node *root,int k)
{
if(root==nil)return Pair<node*,node*>(nil,nil);
Pair<node*,node*>p;
if(root->rev)root->push_down();
if(root->son[0]->size>=k)
{
p=split(root->son[0],k);
root->son[0]=p.second;
root->push_up();
p.second=root;
return p;
}
else
{
p=split(root->son[1],k-root->son[0]->size-1);
root->son[1]=p.first;
root->push_up();
p.first=root;
return p;
}
}
node *merge(node *a,node *b)
{
if(a==nil)return b;
if(b==nil)return a;
if(a->key<b->key)
{
if(a->rev)a->push_down();
a->son[1]=merge(a->son[1],b);
a->push_up();
return a;
}
else
{
if(b->rev)b->push_down();
b->son[0]=merge(a,b->son[0]);
b->push_up();
return b;
}
}
void work(node *root)
{
if(root==nil)return ;
if(root->rev)root->push_down();
work(root->son[0]),write(root->val),putchar(' '),work(root->son[1]);
}
int n,m,l,r;
int main()
{
nil->size=0,Root=nil;
read(n),read(m);
for(int i=1;i<=n;i++)Root=merge(Root,new node(i));
while(m--)
{
read(l),read(r);
Pair<node*,node*>p=split(Root,l-1);
Pair<node*,node*>t=split(p.second,r-l+1);
t.first->rev^=1;
Root=merge(p.first,merge(t.first,t.second));
}
work(Root);
}
偷偷說一句,我寫的Splay沒有我寫的非旋Treap跑得快