• 文艺平衡树


    非常不负责任地水一篇博客
    昨天写的题了,就是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("
    ");
        return 0;
    }
    
  • 相关阅读:
    Aspose.Words三 创建表格
    Aspose.words一 DOM结构
    Aspose.words四 bookmark
    Aspose.Words五 MergeField
    为什么使用Reazor
    C#实现发送给QQ邮件
    T4模板之基础篇
    avalon子孙元素属性监听
    C#设置WebBrowser IE浏览器版本
    【GoLang】GoLang GOPATH 工程管理 最佳实践
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10235273.html
Copyright © 2020-2023  润新知