文艺平衡树
非常不负责任地水一篇博客
昨天写的题了,就是splay的基础操作吧。
我们可以知道将splay左右两个子节点交换就是这个序列的交换。那么我们维护一个tag来记录是否翻转该区间就可以了(注意查询的时候一定要下放!!!)
最后如何输出序列呢?思考splay的性质,其实就是中序遍历就可以啦!
有个小trick就是为了让序列连续,我们可以将一般splay插入的极小值(-2147483647)改为(1),插入的极大值(2147483647)改为(n+2)。
查找需要翻转的区间其实和普通splay删除操作异曲同工,具体实现可以参考代码。
emmm补充一句,这道题平衡树里面记录的是节点编号,而不是值,所以翻转的时候可以直接查找第k大的QAQ,然后在区间上打标记qwq
代码如下:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#define MAXN 200010
using namespace std;
int n,m,root,tot;
struct Node{int ch[2],son,cnt,ff,tag,val;}t[MAXN];
inline void push_up(int x){t[x].son=t[x].cnt+t[t[x].ch[0]].son+t[t[x].ch[1]].son;}
inline void push_down(int x)
{
if(t[x].tag==0) return;
t[t[x].ch[0]].tag^=1;
t[t[x].ch[1]].tag^=1;
t[x].tag=0;
swap(t[x].ch[0],t[x].ch[1]);
}
inline void rotate(int x)
{
int y=t[x].ff;
int z=t[y].ff;
int k=t[y].ch[1]==x;
t[z].ch[t[z].ch[1]==y]=x; t[x].ff=z;
t[y].ch[k]=t[x].ch[k^1]; t[t[x].ch[k^1]].ff=y;
t[x].ch[k^1]=y; t[y].ff=x;
push_up(y),push_up(x);
}
inline void splay(int x,int goal)
{
while(t[x].ff!=goal)
{
int y=t[x].ff;
int z=t[y].ff;
if(z!=goal)
((t[y].ch[0]==x)^(t[z].ch[0]==y))?rotate(x):rotate(y);
rotate(x);
}
if(!goal) root=x;
}
inline void insert(int x)
{
int u=root,ff=0;
while(u&&t[u].val!=x)
ff=u,u=t[u].ch[x>t[u].val];
if(u) t[u].cnt++;
else
{
u=++tot;
if(ff) t[ff].ch[x>t[ff].val]=u;
t[tot].son=t[tot].cnt=1;
t[tot].val=x,t[tot].ff=ff;
}
splay(u,0);
}
inline int _kth(int x)
{
int u=root;
for(;;)
{
push_down(u);
if(t[u].cnt+t[t[u].ch[0]].son<x) x-=t[u].cnt+t[t[u].ch[0]].son,u=t[u].ch[1];
else if(t[t[u].ch[0]].son>=x) u=t[u].ch[0];
else return t[u].val;
}
}
inline void print(int x)
{
push_down(x);
if(t[x].ch[0]) print(t[x].ch[0]);
if(x>=2&&x<=n+1) printf("%d ",t[x].val-1);
if(t[x].ch[1]) print(t[x].ch[1]);
}
inline void solve(int l,int r)
{
int ll=_kth(l),rr=_kth(r+2);
splay(ll,0),splay(rr,ll);
t[t[t[root].ch[1]].ch[0]].tag^=1;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d%d",&n,&m);
for(int i=1;i<=n+2;i++) insert(i);
for(int i=1;i<=m;i++)
{
int l,r;
scanf("%d%d",&l,&r);
solve(l,r);
}
print(root);
printf("\n");
return 0;
}