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, 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

    说明

    n, m leq 100000n,m100000

     

    splay区间操作

    把l-1旋到根,r+1旋到右节点,打上flag标记。

    屠龙宝刀点击就送

    #include <algorithm>
    #include <ctype.h>
    #include <cstdio>
    #define INF 0x7fffffff 
    #define N 100010
    
    using namespace std;
    inline void read(int &x)
    {
        x=0;bool f=0;
        register char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=1;
        for(; isdigit(ch);ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
        x=f?(~x)+1:x;
    }
    struct node
    {
        int data,pos;
        bool operator<(node a)const
        {
            if(data==a.data) return pos<a.pos;
            return data<a.data;
        }
    }d[N];
    int data[N],flag[N],ch[N][2],fa[N],siz[N],root,n,m,cn,mn[N],pos[N];
    inline int min(int a,int b) {return a>b?b:a;}
    inline void pushup(int x)
    {
        mn[x]=min(data[x],min(mn[ch[x][0]],mn[ch[x][1]]));
        if(mn[x]==data[x]) pos[x]=x;
        else if(mn[x]==mn[ch[x][0]]) pos[x]=pos[ch[x][0]];
        else pos[x]=pos[ch[x][1]];
        siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
    }
    inline void pushdown(int x)
    {
        if(flag[x])
        {
            flag[x]=0;
            flag[ch[x][0]]^=1;
            swap(ch[ch[x][0]][0],ch[ch[x][0]][1]);
            flag[ch[x][1]]^=1;
            swap(ch[ch[x][1]][0],ch[ch[x][1]][1]);
        }
    }
    inline int son(int x) {return ch[fa[x]][1]==x;}
    int getkth(int rt,int k)
    {
        pushdown(rt);
        int l=ch[rt][0];
        if(siz[l]+1==k) return rt;
        if(k<siz[l]+1) return getkth(ch[rt][0],k);
        return getkth(ch[rt][1],k-(siz[l]+1));
    }
    inline void rotate(int x)
    {
        int y=fa[x],z=fa[y],b=son(x),c=son(y),a=ch[x][!b];
        if(z) ch[z][c]=x;else root=x;fa[x]=z;
        if(a) fa[a]=y;ch[y][b]=a;
        ch[x][!b]=y;fa[y]=x;
        pushup(y);pushup(x);
    }
    void splay(int x,int i)
    {
        while(fa[x]!=i)
        {
            int y=fa[x],z=fa[y];
            if(z==i) rotate(x);
            else 
            {
                pushdown(z);
                pushdown(y);
                pushdown(x);
                if(son(x)==son(y))
                {
                    rotate(y);
                    rotate(x);
                }
                else 
                {
                    rotate(x);
                    rotate(x);
                }
            }
        }
    }
    void reverse(int l,int r)
    {
        int ll=getkth(root,l-1),rr=getkth(root,r+1);
        splay(ll,0);
        splay(rr,ll);
        int p=ch[rr][0];
        flag[p]^=1;
        swap(ch[p][0],ch[p][1]);
    }
    void dfs(int x)
    {
        if(!x) return;
        pushdown(x);
        dfs(ch[x][0]);
        if(x>1&&x<n+2) printf("%d ",data[x]-1);
        dfs(ch[x][1]);
    }
    int main()
    {
        read(n);
        read(m);
        for(int i=2;i<=n+1;i++)
        {
            data[i]=i-1;
            d[i].data=i-1;
            d[i].pos=i;
        }
        sort(d+2,d+2+n);
        for(int i=2;i<=n+1;i++) data[d[i].pos]=i;
        data[0]=data[1]=data[n+2]=INF;
        for(int i=0;i<=n+2;i++) mn[i]=INF;
        root=1;
        siz[0]=0;
        for(int i=1;i<=n+2;i++)
        {
            fa[i]=i-1;
            ch[i][1]=i+1;
        }
        ch[n+2][1]=0;
        for(int i=n+2;i>=1;i--) pushup(i);
        for(int l,r,i=1;i<=m;i++)
        {
            read(l);
            read(r);
            reverse(l+1,r+1);
        }
        dfs(root);
        return 0;
    }
    我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。
  • 相关阅读:
    序列化二叉树
    把二叉树打印成多行
    按之字形打印数据
    对称的二叉树
    二叉树的下一个结点
    删除链表中重复的结点
    c语言中数组名a和&a详细介绍
    C语言输出格式
    回文素数
    求平均成绩
  • 原文地址:https://www.cnblogs.com/ruojisun/p/7339567.html
Copyright © 2011-2022 走看看