文艺平衡树

非常不负责任地水一篇博客
昨天写的题了,就是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;
}
posted @ 2019-01-07 19:48  风浔凌  阅读(158)  评论(0编辑  收藏  举报