• P3391 【模板】文艺平衡树(Splay) 平衡树


      

    题目背景

    这是一道经典的Splay模板题——文艺平衡树。

    题目描述

    您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1

    输入格式

    第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2, cdots n-1,n)(1,2,n1,n) m表示翻转操作次数

    接下来m行每行两个数 [l,r][l,r] 数据保证 1 leq l leq r leq n1lrn

    输出格式

    输出一行n个数字,表示原始序列经过m次变换后的结果

    输入输出样例

    输入 #1
    5 3
    1 3
    1 3
    1 4
    输出 #1
    4 3 2 1 5


    这题搞了好久 把权值平衡树和区间平衡树搞混了

    这题看似翻转了 其BST性质被破坏了 其实没有 下标仍然保持BST性质 只是val交换了


    在最左和右分别插入一个值 方便维护

    翻转时
    l=kth(l);r=kth(r+2); 那么根结点的右儿子的左子树就是序列 l-r

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define ll long long
    #define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
    #define pb push_back
    #define inf 0x3f3f3f3f
    #define CLR(A,v)  memset(A,v,sizeof A)
    typedef pair<int,int>pii;
    //////////////////////////////////
    const int N=2e6+10;
    
    
    int son[N][2],fa[N],siz[N],cnt[N],val[N],ncnt,root,col[N],n,m;
    
    
    int chk(int x)
    {
        return son[fa[x]][1]==x;
    }
    void up(int x)
    {
        siz[x]=siz[son[x][1]]+siz[son[x][0]]+cnt[x];
    }
    void down(int x)
    {
        if(col[x])
        {
            col[son[x][0]]^=1;
            col[son[x][1]]^=1;
            col[x]=0;
            swap(son[x][0],son[x][1]);
        }
    }
    void rotate(int x)
    {
        int y=fa[x],z=fa[y],k=chk(x),w=son[x][k^1];
        son[y][k]=w;fa[w]=y;
        son[z][chk(y)]=x;fa[x]=z;
        son[x][k^1]=y;fa[y]=x;
        up(x);up(y);
    }
    
    void splay(int x,int goal=0)
    {
        while(fa[x]!=goal)
        {
            int y=fa[x],z=fa[y];
            if(z!=goal)
            {
                if(chk(y)==chk(x))rotate(y);
                else rotate(x);
            }
            rotate(x);
        }
        if(!goal)root=x;
    }
    void insert(int x)
    {
        int pos=root,p=0;
        while(pos&&val[pos]!=x)p=pos,pos=son[pos][x>val[pos]];
        if(pos)cnt[pos]++;
        else
        {
            pos=++ncnt;
            if(p)son[p][x>val[p]]=pos;
            son[pos][0]=son[pos][1]=0;
            cnt[pos]=siz[pos]=1;
            val[pos]=x;fa[pos]=p;
        }
        splay(pos);
    }
    int kth(int k)
    {
        int pos=root;
        while(1)
        {
            down(pos);
            if(son[pos][0]&&siz[son[pos][0]]>=k)pos=son[pos][0];
            else if(k>siz[son[pos][0]]+cnt[pos])k-=siz[son[pos][0]]+cnt[pos],pos=son[pos][1];
            else {splay(pos);return pos;}
        }
    }
    void output(int x)
    {
        down(x);
        if(son[x][0])output(son[x][0]);
        if(val[x]>1&&val[x]<n+2)printf("%d ",val[x]-1);
        if(son[x][1])output(son[x][1]);
    }
    void work(int l,int r)
    {
       // printf("aaa");
        l=kth(l);r=kth(r+2);
       // printf("vall=%d valr=%d
    ",val[l],val[r]);
        splay(l);splay(r,l);
        col[son[son[root][1]][0]]^=1;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        rep(i,1,n+2)insert(i);
        while(m--)
        {
            int l,r;scanf("%d%d",&l,&r);
            work(l,r);
        }
        output(root);
    }
    View Code


  • 相关阅读:
    单向认证
    电商积分支付系统构建经验与总结
    python decimal.quantize()参数rounding的各参数解释与行为
    mysql 由decimal 引起的 Warning: Data truncated for column
    aliyun centos14.04 trusty 上安装docker1.12.1
    使用 py.test 对 python 代码进行测试
    mysql常用增删改查命令(纯纪录.orm用得基本功都没了。)
    python 协程库gevent学习--gevent数据结构及实战(四)
    http请求头中的content-type属性
    坚持做技术写作
  • 原文地址:https://www.cnblogs.com/bxd123/p/11298044.html
Copyright © 2020-2023  润新知