文艺平衡树(splay)

文艺平衡树(luogu)

Description

题目描述

您需要写一种数据结构(可参考题目标题),来维护一个有序数列。

其中需要提供以下操作:翻转一个区间,例如原有序序列是 5\ 4\ 3\ 2\ 15 4 3 2 1,翻转区间是 [2,4][2,4] 的话,结果是 5\ 2\ 3\ 4\ 15 2 3 4 1。

输入格式

第一行两个正整数 n,mn,m,表示序列长度与操作个数。序列中第 ii 项初始为 ii。
接下来 mm 行,每行两个正整数 l,rl,r,表示翻转的区间。

输出格式

输出一行 nn 个正整数,表示原始序列经过 mm 次变换后的结果。

Code

#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int N=100010,inf=999999999;
int sum,n,root,m,l,r,d[N],fa[N],size[N],s[N][2],v[N],tag[N];
inline int which(int x)
{
    return x==s[fa[x]][0]?0:1;
}
inline void push_up(int g)
{
    if(g){
        size[g]=1;
        if(s[g][0]) size[g]+=size[s[g][0]];
        if(s[g][1]) size[g]+=size[s[g][1]];
    }
}
void built(int l,int r,int &g)
{
    if(l>r) return ;
    g=++sum;
    size[g]=1;
    int mid=(l+r)>>1;
    v[g]=d[mid];
    built(l,mid-1,s[g][0]);
    built(mid+1,r,s[g][1]);
    fa[s[g][0]]=fa[s[g][1]]=g;
    push_up(g);
}
inline void push_down(int g)
{
    if(g && tag[g]){
        tag[s[g][0]]^=1,tag[s[g][1]]^=1;
        swap(s[g][0],s[g][1]),tag[g]=0;
    }
}
inline int find(int x)
{
    int now=root;
    while(1)
    {
        push_down(now);
        if(size[s[now][0]]>=x) now=s[now][0];
        else
        {
            x-=size[s[now][0]]+1;
            if(x>0) now=s[now][1];
            else return now;
        }
    }
}
inline void rotate(int x)
{
    int f=fa[x],oldf=fa[f];
    push_down(f),push_down(x);
    int w=which(x),ww=which(f);
    s[f][w]=s[x][w^1];
    fa[s[x][w^1]]=f;
    fa[f]=x,fa[x]=oldf;
    s[x][w^1]=f;
    if(oldf) s[oldf][s[oldf][1]==f]=x;
    push_up(f),push_up(x);
}
inline void splay(int x,int g)
{
    for(int i;(i=fa[x])!=g;rotate(x))
        if(fa[i]!=g) rotate(which(i)==which(x)?i:x);
    if(g==0) root=x;
}
inline void re(int l,int r)
{
    l=find(l-1),r=find(r+1);
    splay(l,0),splay(r,l);
    int pos=s[s[root][1]][0];
    tag[pos]^=1;
}
void dfs(int x)
{
    push_down(x);
    if(s[x][0]) dfs(s[x][0]);
    if(v[x]!=-inf && v[x]!=inf) printf("%d ",v[x]);
    if(s[x][1]) dfs(s[x][1]);
}
int main()
{
    scanf("%d%d",&n,&m);
    d[1]=-inf,d[n+2]=inf;
    for(int i=1;i<=n;i++) d[i+1]=i;
    built(1,n+2,root);
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&l,&r);
        re(l+1,r+1);
    }
    dfs(root);
    return 0;
}

原文地址:https://www.cnblogs.com/hsez-cyx/p/12244750.html

时间: 2024-10-18 09:39:57

文艺平衡树(splay)的相关文章

Tyvj P1729 文艺平衡树 Splay

题目: http://tyvj.cn/p/1729 P1729 文艺平衡树 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 此为平衡树系列第二道:文艺平衡树 描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入格式 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n)  m表示翻转操作次数

BZOJ3223: Tyvj 1729 文艺平衡树 [splay]

3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3595  Solved: 2029[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 Input 第一行为n,m n表示初始序列有n个数,这个序列依次

洛谷 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][l,r] 数据保证 1≤l≤r≤n 输出格式: 输出一行n个数字,表示原始序列经过m次变换后的结果

[BZOJ3223] [Tyvj1729] 文艺平衡树 (splay)

Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是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

JZYZOJ1998 [bzoj3223] 文艺平衡树 splay 平衡树

http://172.20.6.3/Problem_Show.asp?id=1998 平衡树区间翻转的板子,重新写一遍,给自己码一个板子. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<cstdlib> 7 using namespace std; 8 cons

[Bzoj3223][Tyvj1729] 文艺平衡树(splay/无旋Treap)

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3223 平衡树处理区间问题的入门题目,普通平衡树那道题在维护平衡树上是以每个数的值作为维护的标准,而处理区间问题时,维护平衡树的应该是每个位置的下标,所以平衡树中序遍历时应该是当前区间的样子.例如: {1 2 3 4 5}翻转区间1 3,则中序遍历应该输出{3,2,1,4,5}. 提供splay和无旋Treap的做法. splay做法: 1 #include<bits/stdc++.h>

bzoj 3223 文艺平衡树 Splay 打标志

是NOI2003Editor的一个子任务 1 #include <cstdio> 2 #include <vector> 3 #define maxn 100010 4 using namespace std; 5 6 struct Splay { 7 int pre[maxn], son[maxn][2], siz[maxn], rev[maxn], root; 8 9 void update( int nd ) { 10 siz[nd] = siz[son[nd][0]]+si

[bzoj3223]文艺平衡树[splay]

//BY HZWER 1 #include<iostream> 2 #include<cstdio> 3 4 using namespace std; 5 6 inline int read() 7 { 8 int x=0,f=1;char ch=getchar(); 9 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 10 while(ch>='0'&&ch<='9'){x=x*10

bzoj 3223/tyvj 1729 文艺平衡树 splay tree

原题链接:http://www.tyvj.cn/p/1729 这道题以前用c语言写的splay tree水过了.. 现在接触了c++重写一遍... 只涉及区间翻转,由于没有删除操作故不带垃圾回收,具体如下: 1 #include<cstdio> 2 #include<cstdlib> 3 #include<iostream> 4 #include<algorithm> 5 const int MAX_N = 100010; 6 struct Node{ 7

[bzoj3223]文艺平衡树(splay区间反转模板)

解题关键:splay模板题. #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> using namespace std; typedef long long ll; const int N = 100005; int ch[N][2],par[N],val[N],cnt[