• 洛谷 P3391 【模板】文艺平衡树


    题目背景

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

    题目描述

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

    输入输出格式

    输入格式:

     

    第一行为n,m(n,m<=100000) 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次变换后的结果

    输入输出样例

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


    splay模板题,维护该序列的中序遍历不变,然后每次通过旋转节点使操作的区间变作一颗字树,然后打上标记即可。
    什么是splay?
    一棵伸展树......
    什么是伸展树?
    最近刚学,我个人的理解,大概就是一个能在不破坏二叉搜索树结构(即中序遍历始终为升序)的情况下
    通过旋转一个节点到他根节点位置使得操作区间恰好全部位于一棵子树内的方法。


    然后就打上标记,之后在类似线段树一样的pushdown传递信息就好了。

    代码如下:
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define mod
    #define mid (R+L>>1)
    #define M 2000010
    using namespace std;
    LL read(){
        LL nm=0,oe=1;char cw=getchar();
        while(!isdigit(cw)) oe=cw=='-'?-oe:oe,cw=getchar();
        while(isdigit(cw)) nm=nm*10+(cw-'0'),cw=getchar();
        return nm*oe;
    }
    LL n,m,l[M],r[M],tp[M],ad,sz[M],tg[M],ace,a,b,p,q,cnt;
    bool flag=false;
    void pushdown(LL x){
        if(tg[x]==0) return;
        tg[x]=0,swap(l[x],r[x]);
        tg[l[x]]^=1,tg[r[x]]^=1;
    }
    void pushup(LL x){sz[x]=sz[l[x]]+sz[r[x]]+1;}
    LL build(LL L,LL R,LL rt){
        if(L>R) return 0;
        tp[mid]=rt,sz[mid]=1;
        if(L==R) return L;
        l[mid]=build(L,mid-1,mid);
        r[mid]=build(mid+1,R,mid);
        sz[mid]+=sz[l[mid]]+sz[r[mid]];
        return mid;
    }
    void rotate(LL x){
        if(ace==x) return;
        LL top=tp[x];
        pushdown(top),pushdown(x);
        if(top==ace) ace=x,tp[x]=n+1,tp[top]=x;
        else{
            if(l[tp[top]]==top) l[tp[top]]=x;
            else r[tp[top]]=x;
            tp[x]=tp[top],tp[top]=x;
        }
        if(l[top]==x) l[top]=r[x],tp[r[x]]=top,r[x]=top;
        else r[top]=l[x],tp[l[x]]=top,l[x]=top;
        pushup(top),pushup(x);
    }
    void oper(LL x){
        if(x==ace||tp[x]==ace){return;}
        LL top=tp[x];
        pushdown(top);
        if(tp[top]==ace) rotate(x);
        else if(l[l[tp[top]]]==x||r[r[tp[top]]]==x) rotate(top);
        else rotate(x);
    }
    LL find(LL x,LL pos){
        pushdown(x);
        if(sz[l[x]]==pos-1) return x;
        if(sz[l[x]]<pos-1) return find(r[x],pos-sz[l[x]]-1);
        else return find(l[x],pos);
    }
    void ans(LL x){
        if(x==0) return;
        pushdown(x);
        ans(l[x]);
        if(x<n&&x>1){
            if(flag) printf(" ");
            flag=true;
            printf("%lld",x-1);
        }
        ans(r[x]);
    }
    int main(){
        n=read()+2,m=read(),ace=build(1,n,n+1);
        while(m--){
            a=read(),b=read();
            p=find(ace,a),q=find(ace,b+2);
            while(tp[q]!=ace&&q!=ace) oper(q);
            if(q!=ace) rotate(q);
            while(tp[p]!=ace) oper(p);
            tg[r[p]]^=1;
        }
        ans(ace);
        return 0;
    }
    
    

    我这里还是写的比较模糊,我也是通过了解别人的博客才理解了splay

    就是这个 -> http://blog.csdn.net/skydec/article/details/20151805

  • 相关阅读:
    [网络流24题]骑士共存问题
    [网络流24题]魔术球问题
    [网络流24题]飞行员配对方案问题
    bzoj2741【FOTILE模拟赛】L(可持久化trie树+分块)
    bzoj4103[Thu Summer Camp 2015]异或运算(可持久化trie树)
    bzoj[3881]Divljak(dfs序+树状数组+fail树)
    bzoj1444 有趣的游戏(AC自动机+矩阵乘法)
    bzoj1195 最短母串
    bzoj2938 病毒
    poj 3134 Power Calculus (IDA*)
  • 原文地址:https://www.cnblogs.com/OYJason/p/7887057.html
Copyright © 2020-2023  润新知