【模板】文艺平衡树(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,?n?1,n) m表示翻转操作次数

接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r \leq n1≤l≤r≤n

输出格式:

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

#include <bits/stdc++.h>

using namespace std;
const int maxn = 100000+5;
const int inf = 2000000008;
int root,tot,ch[maxn][2],lazy[maxn],fa[maxn],siz[maxn];
int n,m;
struct Splay{
    void init(int t, int par = 0){
        ch[t][0] = ch[t][1] = 0; fa[t] = par;
    }
    void up(int t){
        siz[t] = siz[ch[t][1]] + siz[ch[t][0]] + 1;
    }
    void down(int t){
        if(!lazy[t])return;
        swap(ch[t][0], ch[t][1]);
        lazy[ch[t][0]] ^= 1;
        lazy[ch[t][1]] ^= 1;
        lazy[t] = 0;
    }
    void init(){
        init(0, 0);
        tot = root = 0;
    }
    int find( int x, int t = root){
        down(t);
        if(!x)return t;
        if(x > siz[ch[t][0]]+1)return find(x - siz[ch[t][0]] - 1, ch[t][1]);
        if(x == siz[ch[t][0]] + 1)return t;
        return find(x, ch[t][0]);
    }
    void rotate(int x, int d){
        int y = fa[x];
        down(y),down(x);
        ch[y][d^1] = ch[x][d];
        if(ch[x][d])fa[ch[x][d]] = y;
        fa[x] = fa[y];
        if(fa[y]){
            if(y == ch[fa[y]][d])ch[fa[y]][d] = x;
            else ch[fa[y]][d^1] = x;
        }
        ch[x][d] = y;fa[y] = x;
        up(y),up(x);
    }
    void splay(int x, int targrt){

        while(fa[x] != targrt){
            int y = fa[x];
            if(x == ch[y][0]){
                if(targrt != fa[y]&& y == ch[fa[y]][0])
                    rotate(y, 1);
                rotate(x, 1);
            }
            else {
                if(targrt != fa[y]&& y == ch[fa[y]][1])
                    rotate(y, 0);
                rotate(x, 0);
            }
        }
        if(!targrt)root = x;
    }
   int build(int f, int l, int r){
        if(l > r)return 0;
        int m = (l + r) >> 1;
        init(m, f);
        ch[m][0] = build(m, l, m-1);
        ch[m][1] = build(m, m+1, r);
        up(m);
        return m;
   }
   void rev(int l, int r){
        int L = find(l);
        int R = find(r+2);
        splay(L, 0);
        splay(R, L);
        //int x = ch[R][0];
        int x = ch[ch[root][1]][0];
        lazy[x] ^= 1;

   }

}Tr;
int main()
{

    scanf("%d%d",&n,&m);
    root = Tr.build(0, 1, n+2);
    while(m--){
        int opt,x;
        scanf("%d%d",&opt,&x);
        Tr.rev(opt, x);
    }
    for(int i = 1; i <= n; i++)printf("%d ",Tr.find(i+1)-1);
    return 0;
}

原文地址:https://www.cnblogs.com/EdSheeran/p/8688559.html

时间: 2024-08-02 19:07:49

【模板】文艺平衡树(Splay)的相关文章

洛谷 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次变换后的结果

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个数,这个序列依次

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

[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

模板 文艺平衡树

Splay模板,学完觉得比Treap简单,不过均摊的logn不能可持久化. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define ls ch[0] 5 #define rs ch[1] 6 struct trnt{ 7 int ch[2]; 8 int chd; 9 int wgt; 10 int fa; 11 int v; 12 }tr[10000000]; 13 int root

[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