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

//建树是按照数组下标建的
//不是数组的值 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int N=1e5+5;

int n,m;
struct NODE
{
    int size,v;
    NODE *fa;
    NODE *son[2];
    bool rev;
    inline int cmp(int val)
    {
        return (v==val)?-1:val>v;
    }
    inline void update()
    {
        this->size=son[0]->size+son[1]->size+1;
    }
}node[N];

typedef NODE* Tree;
Tree Root,null,now_node;

inline int read()
{
    char c=getchar();int num=0,f=1;
    for(;!isdigit(c);c=getchar())
        f=c=='-'?-1:f;
    for(;isdigit(c);c=getchar())
        num=num*10+c-'0';
    return num;
}

inline void init()
{
    null=node;
    null->size=null->v=0;
    null->fa=null->son[0]=null->son[1]=null;
    Root=now_node=node;
}

inline Tree new_node(int x,Tree fa)
{
    ++now_node;
    now_node->rev=false;
    now_node->size=1;
    now_node->v=x;
    now_node->son[0]=now_node->son[1]=null;
    now_node->fa=fa;
    return now_node;
}

inline Tree build(int l,int r,Tree fa)
{
    if(l>r)
        return null;
    int mid=l+r>>1;
    Tree cur=new_node(mid,fa);
    if(l<r)
    {
        cur->son[0]=build(l,mid-1,cur);
        cur->son[1]=build(mid+1,r,cur);
    }
    cur->update();
    return cur;
}

inline void down(Tree root)
{
    if(root->rev)
    {
        Tree tmp=root->son[0];
        root->son[0]=root->son[1];
        root->son[1]=tmp;
        if(root->son[0]!=null)
            root->son[0]->rev^=1;
        if(root->son[1]!=null)
            root->son[1]->rev^=1;
        root->rev=0;
    }
}

inline bool getgx(Tree root)
{
    return root->fa->son[1]==root;
}

inline void connect(Tree root,Tree fa,bool flag)
{
    if(fa!=null)
        fa->son[flag]=root;
    root->fa=fa;
}

inline void rotate(Tree root)
{
    Tree fa=root->fa;
    Tree gfa=fa->fa;
    bool a=getgx(root),b=!a;
    connect(root->son[b],fa,a);
    connect(root,gfa,getgx(fa));
    connect(fa,root,b);
    fa->update();
    root->update();
    if(gfa==null)
        Root=root;
}

inline void splay(Tree root,Tree goal)
{
    down(root);
    for(;root->fa!=goal;rotate(root))
    {
        if(root->fa->fa!=goal)
            rotate(getgx(root)==getgx(root->fa)?root->fa:root);
    }
}

inline Tree find(Tree root,int val)
{
    down(root);
    int left=root->son[0]->size+1;
    if(left==val)
        return root;
    if(left>val)
        return find(root->son[0],val);
    return find(root->son[1],val-left);
}

inline void reverse(int l,int r)
{
    Tree a=find(Root,l);
    Tree b=find(Root,r+2);
    splay(a,null);
    splay(b,a);
    Root->update();
    b->son[0]->rev^=1;
}

inline void dfs(Tree root)
{
    down(root);
    if(root->son[0]!=null)
        dfs(root->son[0]);
    if(root->v-1<=n&&root->v-1>=1)
        printf("%d ",root->v-1);
    if(root->son[1]!=null)
        dfs(root->son[1]);
}

int main()
{
    n=read(),m=read();
    init();
    Root=build(1,n+2,null);
    while(m--)
    {
        int l=read(),r=read();
        reverse(l,r);
    }
    dfs(Root);
    return 0;
}
原文地址:https://www.cnblogs.com/lovewhy/p/8717267.html