zoukankan      html  css  js  c++  java
  • luogu3391

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

    题目背景

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

    题目描述

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

    Input

    第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n)  m表示翻转操作次数
    接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n 

    Output

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

    Sample Input

    5 3
    1 3
    1 3
    1 4

    Sample Output

    4 3 2 1 5

    HINT

    N,M<=100000

    sol:闲的蛋疼打了一遍splay板子,还挂了一发。Ps:注意下传Rev标记

    #include <bits/stdc++.h>
    using namespace std;
    typedef int ll;
    inline ll read()
    {
        ll s=0;
        bool f=0;
        char ch=' ';
        while(!isdigit(ch))
        {
            f|=(ch=='-'); ch=getchar();
        }
        while(isdigit(ch))
        {
            s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
        }
        return (f)?(-s):(s);
    }
    #define R(x) x=read()
    inline void write(ll x)
    {
        if(x<0)
        {
            putchar('-'); x=-x;
        }
        if(x<10)
        {
            putchar(x+'0');    return;
        }
        write(x/10);
        putchar((x%10)+'0');
        return;
    }
    #define W(x) write(x),putchar(' ')
    #define Wl(x) write(x),putchar('
    ')
    const int N=100005,inf=0x3f3f3f3f;
    int n,m;
    namespace Pht
    {
        int Points=0,Root;
        int Child[N][2],Parent[N];
        int Size[N];
        int Quanzhi[N];
        bool Rev[N];
    
        inline void Init();
        inline int Check(int x);
        inline void PushUp(int x);
        inline void PushDown(int x);
        inline void Rotate(int x);
        inline void Splay(int At,int To);
        inline void Insert(int Val);
        inline int Ask_Kth(int Id);
        inline void Reverse(int l,int r);
        inline void Output(int Now);
        inline void Solve();
        
        inline void Init()
        {
            int i;
            Insert(-inf);
            for(i=1;i<=n;i++) Insert(i);
            Insert(inf);
        }
        inline int Check(int x)
        {
            return (Child[Parent[x]][0]==x)?0:1;
        }
        inline void PushUp(int x)
        {
            Size[x]=Size[Child[x][0]]+Size[Child[x][1]]+1;
        }
        inline void PushDown(int x)
        {
            if(!Rev[x]) return;
            swap(Child[x][0],Child[x][1]);
            Rev[x]=0;
            Rev[Child[x][0]]^=1;
            Rev[Child[x][1]]^=1;
        }
        inline void Rotate(int x)
        {
            int y,z,oo;
            y=Parent[x];
            z=Parent[y];
            oo=Check(x);
            Child[y][oo]=Child[x][oo^1]; Parent[Child[x][oo^1]]=y;
            Child[z][Check(y)]=x; Parent[x]=z;
            Child[x][oo^1]=y; Parent[y]=x;
            PushUp(x); PushUp(y);
        }
        inline void Splay(int At,int To)
        {
            while(Parent[At]!=To)
            {
                int Father=Parent[At];
                if(Parent[Father]==To)
                {
                    Rotate(At);
                }
                else if(Check(At)==Check(Father))
                {
                    Rotate(Father); Rotate(At);
                }
                else
                {
                    Rotate(At); Rotate(At);
                }
            }
            if(To==0) Root=At;
        }
        inline void Insert(int Val)
        {
            int Now=Root,Par=0;
            while(Now)
            {
                Par=Now;
                Now=Child[Now][(Val>Quanzhi[Now])?1:0];
            }
            Now=++Points;
            if(Par)
            {
                Child[Par][(Val>Quanzhi[Par])?1:0]=Now;
            }
            Parent[Now]=Par;
            Child[Now][0]=Child[Now][1]=0;
            Quanzhi[Now]=Val;
            Size[Now]=1;
            Splay(Now,0);
        }
        inline int Ask_Kth(int Id)
        {
            int Now=Root;
            while(Now)
            {
                PushDown(Now);
                if(Size[Child[Now][0]]>=Id)
                {
                    Now=Child[Now][0];
                }
                else if(Size[Child[Now][0]]+1==Id)
                {
                    return Now;
                }
                else
                {
                    Id=Id-Size[Child[Now][0]]-1;
                    Now=Child[Now][1];
                }
            }
        }
        inline void Reverse(int l,int r)
        {
            int ll=Ask_Kth(l),rr=Ask_Kth(r+2);
            Splay(ll,0);
            Splay(rr,ll);
            int Pos=Child[rr][0];
            Rev[Pos]^=1;
        }
        inline void Output(int Now)
        {
            PushDown(Now);
            if(Child[Now][0]) Output(Child[Now][0]);
            if(Quanzhi[Now]>=1&&Quanzhi[Now]<=n) W(Quanzhi[Now]);
            if(Child[Now][1]) Output(Child[Now][1]);
        }
        inline void Solve()
        {
            Init();
            while(m--)
            {
                int l=read(),r=read();
                Reverse(l,r);
            }
            Output(Root);
        }
    }
    int main()
    {
        R(n); R(m);
        Pht::Solve();
        return 0;
    }
    /*
    input
    5 3
    1 3
    1 3
    1 4
    output
    4 3 2 1 5
    */
    View Code
  • 相关阅读:
    svn提交失败 :“svn: E200007: Commit failed”
    POI导入excel文件2
    poi导出excel
    zookeeper的安装及共享锁的应用
    微信支付---统一下单
    Socket通信的简单例子
    HTML CSS + DIV实现整体布局
    很认真的聊一聊程序员的自我修养
    POI上传,导入excel文件到服务器1
    时序数据库技术体系 – InfluxDB 多维查询之倒排索引
  • 原文地址:https://www.cnblogs.com/gaojunonly1/p/10729887.html
Copyright © 2011-2022 走看看