题目背景
这是一道经典的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次变换后的结果
输入输出样例
说明
n, m leq 100000n,m≤100000
//建树是按照数组下标建的 //不是数组的值 #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; }