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,?n?1,n) m表示翻转操作次数

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

输出格式:

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

输入输出样例

输入样例#1:

5 3
1 3
1 3
1 4

输出样例#1:

4 3 2 1 5

说明

n, m \leq 100000n,m≤100000

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 100010
using namespace std;
int n,m,tot;
int root,siz[MAXN],fa[MAXN],flag[MAXN],key[MAXN],ch[MAXN][2],cnt[MAXN],ans[MAXN];
void updeat(int rt){
    int l=ch[rt][0],r=ch[rt][1];
    siz[rt]=siz[l]+siz[r]+1;
}
void pushdown(int now){
    if(flag[now]){
        flag[ch[now][0]]^=1;
        flag[ch[now][1]]^=1;
        swap(ch[now][0],ch[now][1]);
        flag[now]=0;
    }
}
int getson(int x){
    return ch[fa[x]][1]==x;
}

void rotate(int x){
    int y=fa[x],z=fa[y],b=getson(x),c=getson(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;
    updeat(y);updeat(x);
}

void splay(int x,int i){
    while(fa[x]!=i){
        int y=fa[x],z=fa[y];
        if(z==i){
            rotate(x);
        }else{
            if(getson(x)==getson(y)){
               rotate(y); rotate(x);
            }else{
               rotate(x); rotate(x);
            }
        }
    }
}
int findx(int x){
    int now=root;
    while(1){
        pushdown(now);
        if(ch[now][0]&&x<=siz[ch[now][0]])
            now=ch[now][0];
        else{
            int tmp=(ch[now][0]?siz[ch[now][0]]:0)+1;
            if(x<=tmp)    return now;
            x-=tmp;
            now=ch[now][1];
        }
    }
}
int build(int l,int r,int f){
    int now=(l+r)/2;
    fa[now]=f;
    key[now]=ans[now];
    if(l<now)    ch[now][0]=build(l,now-1,now);
    if(r>now)    ch[now][1]=build(now+1,r,now);
    updeat(now);
    return now;
}
void print(int now){
    pushdown(now);
    if(ch[now][0])    print(ch[now][0]);
    ans[++tot]=key[now];
    if(ch[now][1])    print(ch[now][1]);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n+2;i++)
        ans[i]=i-1;
    root=build(1,n+2,0);
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        y=y+2;
        int xx=findx(x),yy=findx(y);
        splay(xx,0);splay(yy,xx);
        flag[ch[ch[root][1]][0]]^=1;
    }
    print(root);
    for(int i=1;i<=n;i++)
        printf("%d ",ans[i+1]);
}
时间: 2024-10-10 14:53:08

P3391 【模板】文艺平衡树(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