[BZOJ]3223 文艺平衡树 区间翻转

3223: Tyvj 1729 文艺平衡树

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 4861   Solved: 2851
[ Submit][ Status][ Discuss]

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

1 3

1 4

Sample Output

4 3 2 1 5

HINT



N,M<=100000

Source

[ Submit][ Status][ Discuss]


HOME Back

普通的区间翻转而已.

#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=100005;
int siz[maxn],c[maxn][2],newone,s[maxn],rev[maxn],fa[maxn],n,m,tot,root,l,r,w[maxn];
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){
    register int x=0,f=1;
    register char ch=nc();
    while(ch<'0'||ch>'9'){if(ch=='-')f*=-1;ch=nc();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=nc();
    return f*x;
}
inline int newnode(){
    newone=++tot;
    siz[newone]=fa[newone]=c[newone][0]=c[newone][1]=0;
    return newone;
}
inline void update(int x){
    if(!x) return;
    siz[x]=siz[c[x][0]]+siz[c[x][1]]+1;
}
inline void pushdown(int x){
    if(!x) return;
	if(rev[x]){
	   rev[x]^=1,rev[c[x][0]]^=1,rev[c[x][1]]^=1;
	   swap(c[x][0],c[x][1]);
	}
}
inline void rotate(int x,int &_wanna){
    int y=fa[x],z=fa[y];
    int l=(c[y][0]!=x),r=l^1;
    if(y!=_wanna) c[z][c[z][0]!=y]=x;
    else _wanna=x;
    fa[x]=z,fa[y]=x,fa[c[x][r]]=y;
    c[y][l]=c[x][r],c[x][r]=y;
    update(y),update(x);
}
inline void splay(int x,int &_wanna){
    int top=0;
	for(int i=x;i;i=fa[i]) s[++top]=i;
	for(int i=top;i;i--) pushdown(s[i]);
	for(int f;x!=_wanna;rotate(x,_wanna))
     if((f=fa[x])!=_wanna)
       rotate(((c[fa[f]][0]==f^c[f][0]==x)?x:f),_wanna);
}
int find(int k,int x){
	pushdown(k);
    if(x-1==siz[c[k][0]]) return k;
    if(x>siz[c[k][0]]+1) return find(c[k][1],x-siz[c[k][0]]-1);
    else return find(c[k][0],x);
}
void build(int lf,int rg,int who){
	int mid=(lf+rg)>>1;
	w[who]=mid;
	if(lf==rg) {siz[who]=1;return;}
	if(lf<mid) {c[who][0]=newnode();fa[c[who][0]]=who;build(lf,mid-1,c[who][0]);}
    if(rg>mid) {c[who][1]=newnode();fa[c[who][1]]=who;build(mid+1,rg,c[who][1]);}
	update(who);
}
inline void init(){
    root=1,tot=2;
    fa[root]=0,c[root][1]=2,fa[2]=1,c[2][0]=newnode(),fa[c[2][0]]=2;
    build(1,n,c[2][0]);
    update(2),update(1);
}
void dfs(int x){
    pushdown(x);
	if(c[x][0]) dfs(c[x][0]);
    if(w[x]) printf("%d ",w[x]);
    if(c[x][1]) dfs(c[x][1]);
}
int main(){
    n=read(),m=read();
	init();
    while(m--){
      l=read(),r=read();
      l=find(root,l);splay(l,root);
      r=find(root,r+2);splay(r,c[l][1]);
      rev[c[r][0]]^=1;
	}
	dfs(root);
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值