zoukankan      html  css  js  c++  java
  • P3391 【模板】文艺平衡树(Splay)

    题目背景

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

    题目描述

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

    输入输出格式

    输入格式:

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

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

    输出格式:

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

    输入输出样例

    输入样例#1: 
    5 3
    1 3
    1 3
    1 4
    输出样例#1: 
    4 3 2 1 5

    说明

    n,m≤100000

    代码

    l-1r+1分别旋转到根节点和根节点右儿子处,
    那么r+1的左子树即是区间[l,r]
    在其根处打上标记然后在查询k大和输出中序遍历时下传标记即可。
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100000+100;
    int ch[maxn][2],size[maxn],cnt[maxn],val[maxn],fa[maxn],rev[maxn];
    int root,ncnt;
    int n,m;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return x*f;
    }
    inline void swap(int& x,int&y)
    {
        x^=y,y^=x,x^=y;
    }
    inline void pushup(int u)
    {
        size[u]=size[ch[u][0]]+size[ch[u][1]]+cnt[u];
    }
    inline void pushdown(int u)
    {
        if(rev[u])
        {
            rev[ch[u][0]]^=1;
            rev[ch[u][1]]^=1;
            swap(ch[u][0],ch[u][1]);
            rev[u]^=1;
        }
    }
    inline int chk(int u)
    {
        return ch[fa[u]][1]==u;
    }
    void rotate(int u)
    {
        int f=fa[u],ff=fa[f],k=chk(u),s=ch[u][k^1];
        ch[f][k]=s,fa[s]=f;
        ch[ff][chk(f)]=u,fa[u]=ff;
        ch[u][k^1]=f,fa[f]=u;
        pushup(u),pushup(f);
    }
    void splay(int u,int goal=0)
    {
        while(fa[u]!=goal)
        {
            int f=fa[u],ff=fa[f];
            if(ff!=goal)
            {
                if(chk(u)==chk(f))rotate(f);
                else rotate(u);
            }
            rotate(u);
        }
        if(!goal)root=u;
    }
    void insert(int x)
    {
        int u=root,f=0;
        while(u&&val[u]!=x)
        f=u,u=ch[u][x>val[u]];
        if(u)cnt[u]++;
        else 
        {
            u=++ncnt;
            if(f)ch[f][x>val[f]]=u;
            fa[u]=f,val[u]=x;
            cnt[u]=size[u]=1;
            ch[u][0]=ch[u][1]=0;
        }
        splay(u);
    }
    int kth(int k)
    {
        int u=root;
        while(1)
        {
            pushdown(u);
            if(ch[u][0]&&k<=size[ch[u][0]])
            u=ch[u][0];
            else if(k>size[ch[u][0]]+cnt[u])
            k-=size[ch[u][0]]+cnt[u],u=ch[u][1];
            else return u;
        }
    }
    void reverse(int l,int r)
    {
        int x=kth(l),y=kth(r+2);
        splay(x),splay(y,x);
        rev[ch[y][0]]^=1;
    }
    void output(int u)
    {
        pushdown(u);
        if(ch[u][0])output(ch[u][0]);
        if(val[u]&&val[u]<=n)printf("%d ",val[u]);
        if(ch[u][1])output(ch[u][1]);
    }
    int main()
    {
        n=read(),m=read();
        for(int i=0;i<=n+1;i++)insert(i);
        for(int i=1;i<=m;i++)
        {
            int x=read(),y=read();
            reverse(x,y);
        }
        output(root);
        return 0;
    }
    View Code
  • 相关阅读:
    简单工作流实现思路总结
    (转)基于SAML的单点登录介绍
    Kerberos简介
    (转)Java NIO框架Mina、Netty、Grizzly介绍与对比
    职场老好人为何没发展
    如何改变、摆脱职场老好人
    线程的状态转换图
    设计模式分类
    (转)简单的RPC java实现 .
    MYSQL导入CSV格式文件数据执行提示错误(ERROR 1290): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement.
  • 原文地址:https://www.cnblogs.com/DriverBen/p/10884580.html
Copyright © 2011-2022 走看看