早就聽說 Splay 就是不管幹什麼都Splay一下就可以了,但是聽說傻可開腦洞打代碼打了250行,驚恐。
於是先學treap結果沒想到一調試就搞了三個月。但是其實寫過treap再學Splay就相對容易一些了。
那就先學只有區間翻轉的文藝平衡樹。
一開始一直弄不懂它的翻轉操作,感覺很迷。但是其實和treap很像,只不過是以翻兩下爲一組,然後每次Splay把節點旋到指定位置。在三點一線的時候,先旋轉x的父親,再旋轉x,除此之外都直接旋轉x就好了。
除此之外還要注意一些細節問題。一個是關於添加虛節點的問題。比如我們要翻轉[l,r]這個區間,我們可以把r+1這個點Splay到跟,然後把l-1這個點Splay到跟的左兒子,然後直接把l-1的右兒子打上標記。但是如果l==1或r==n,那樣就必須添加一個能表示l-1(0)的節點和一個能表示r+1(n+1)的節點。
Splay有兩種寫法,白書上是沒有父親指針的,但是有父親指針的適用性更強。
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e5+10;
int n,m,root;
int aa;char cc;
int read() {
aa=0;cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
return aa;
}
struct Node{
int son[2],laz,fa,sum;
}node[maxn];
void bld(int pos,int l,int r) {
if(!pos||l>r) return ;
if(l==r) {node[pos].sum=1;return;}
if(pos!=l) node[pos].son[0]=(pos+l)>>1;
if(pos!=r) node[pos].son[1]=(pos+2+r)>>1;
node[node[pos].son[0]].fa=node[node[pos].son[1]].fa=pos;
bld(node[pos].son[0],l,pos-1); bld(node[pos].son[1],pos+1,r);
node[pos].sum+=node[node[pos].son[0]].sum+node[node[pos].son[1]].sum+1;
}
void ud(int pos) {
if(!node[pos].laz||node[pos].sum==1) {
node[pos].laz=0;return ;//
}
swap(node[pos].son[0],node[pos].son[1]);
if(node[pos].son[0]) node[node[pos].son[0]].laz^=1;
if(node[pos].son[1]) node[node[pos].son[1]].laz^=1;
node[pos].laz=0;
}
int find(int pos,int x) {
ud(pos);
if(node[node[pos].son[0]].sum+1==x) return pos;
if(x<=node[node[pos].son[0]].sum) return find(node[pos].son[0],x);
return find(node[pos].son[1],x-(node[node[pos].son[0]].sum+1));
}
void rotate(int pos,int &to) {
int x=node[pos].fa,y=node[x].fa;
int p1=node[x].son[1]==pos,p2=node[y].son[1]==x;
node[x].son[p1]=node[pos].son[!p1];
node[node[pos].son[!p1]].fa=x;//
node[pos].son[!p1]=x;
node[pos].sum=node[x].sum;
node[x].sum=node[node[x].son[0]].sum+node[node[x].son[1]].sum+1;
node[pos].fa=y;node[x].fa=pos;
if(root==x) root=pos;
else {
node[y].son[p2]=pos;
if(x==to) to=pos;
}
}
void splay(int pos,int &to) {
ud(pos);
int x,y,p1,p2;
while(to!=pos) {
x=node[pos].fa;y=node[x].fa;
if(y) ud(y);ud(x);ud(pos);
if(x!=to) {
if(node[x].son[1]==pos ^ node[y].son[1]==x) rotate(pos,to);
else rotate(x,to);
}
rotate(pos,to);
}
}
void fz(int l,int r) {
if(l==r) return ;
int x=find(root,l),y=find(root,r+2);
splay(y,root); splay(x,node[root].son[0]);
node[node[x].son[1]].laz^=1;
}
void dfs(int pos) {
ud(pos);
if(node[pos].son[0]) dfs(node[pos].son[0]);
if(pos>1&&pos<n+2) printf("%d ",pos-1);
if(node[pos].son[1]) dfs(node[pos].son[1]);
}
int main() {
n=read();m=read();
root=(n+3)>>1;
bld(root,1,n+2);
int l,r;
for(int i=1;i<=m;++i) {
l=read();r=read();
fz(l,r);
}
dfs(root);
return 0;
}