题目链接
题目描述
您需要写一种数据结构(可参考题目标题),来维护一个有序数列。
其中需要提供以下操作:翻转一个区间,例如原有序序列是 543215\ 4\ 3\ 2\ 15 4 3 2 1,翻转区间是 [2,4][2,4][2,4] 的话,结果是 523415\ 2\ 3\ 4\ 15 2 3 4 1。
输入格式
第一行两个正整数 n,mn,mn,m ,表示序列长度与操作个数。序列中第 iii 项初始为 iii。
接下来 mmm 行,每行两个正整数 l,rl,rl,r,表示翻转的区间。
输出格式
输出一行 nnn 个正整数,表示原始序列经过 mmm 次变换后的结果。
输入输出样例
输入 #1
5 3
1 3
1 3
1 4
输出 #1
4 3 2 1 5
说明/提示
对于 100%100\%100% 的数据,1≤n,m≤105,1≤l≤r≤n1 \le n, m \leq 10^5,1 \le l \le r \le n1≤n,m≤105,1≤l≤r≤n。
Solution
- 模板题。
Code
FHQ Treap
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<ctime>
using namespace std;
const int maxn=1000020;
int n,m,root,tot;
struct FHQ{int lc,rc;int val,dat,siz,tag;
}tr[maxn];
inline int newnode(int v){tr[++tot].siz=1;tr[tot].val=v;tr[tot].dat=rand();return tot;
}
inline void pushup(int u){tr[u].siz=tr[tr[u].lc].siz+tr[tr[u].rc].siz+1;
}
inline void pushdown(int u){if(tr[u].tag){swap(tr[u].lc,tr[u].rc);tr[tr[u].lc].tag^=1;tr[tr[u].rc].tag^=1;tr[u].tag=0;}
}
inline int merge(int x,int y){if(!x||!y)return x+y;pushdown(x),pushdown(y);if(tr[x].dat<tr[y].dat){tr[x].rc=merge(tr[x].rc,y);pushup(x);return x;}else{tr[y].lc=merge(x,tr[y].lc);pushup(y);return y;}
}
inline void spilt(int u,int k,int &x,int &y){if(!u){x=y=0;return;}pushdown(u);if(k<=tr[tr[u].lc].siz)y=u,spilt(tr[u].lc,k,x,tr[u].lc);elsex=u,spilt(tr[u].rc,k-tr[tr[u].lc].siz-1,tr[u].rc,y);pushup(u);
}
inline int build(int l,int r){int mid=(l+r)>>1;int u=newnode(mid);if(l<mid)tr[u].lc=build(l,mid-1);if(mid<r)tr[u].rc=build(mid+1,r);pushup(u);return u;
}
inline void rev(int l,int r){int a,b,c,d;spilt(root,l-1,a,b);spilt(b,r-l+1,c,d);tr[c].tag^=1;root=merge(a,merge(c,d));
}
inline void print(int u){pushdown(u);if(tr[u].lc)print(tr[u].lc);if(tr[u].val>=1&&tr[u].val<=n)printf("%d ",tr[u].val);if(tr[u].rc)print(tr[u].rc);
}
int main(){srand(time(0));scanf("%d%d",&n,&m);root=build(0,n+1);for(int i=1;i<=m;++i){int l,r;scanf("%d%d",&l,&r);rev(l+1,r+1);}print(root);return 0;
}
Splay
#include<cstdio>
#include<algorithm>
const int maxn=100010;
struct Splay{int val,son[2],fa,tag,siz;
}tr[maxn];
int n,m,tot,root;
inline void pushup(int u){tr[u].siz=tr[tr[u].son[0]].siz+tr[tr[u].son[1]].siz+1;
}
inline void pushdown(int u){if(tr[u].tag){tr[tr[u].son[0]].tag^=1;tr[tr[u].son[1]].tag^=1;std::swap(tr[u].son[0],tr[u].son[1]);tr[u].tag=0;}
}
inline int build(int l,int r,int fa){int u=++tot;int mid=(l+r)>>1;tr[u].val=mid;tr[u].fa=fa;if(l<mid)tr[u].son[0]=build(l,mid-1,u);if(mid<r)tr[u].son[1]=build(mid+1,r,u);pushup(u);return u;
}
inline void rotate(int x){int y=tr[x].fa,z=tr[y].fa;int k=tr[y].son[1]==x;tr[z].son[tr[z].son[1]==y]=x,tr[x].fa=z;tr[y].son[k]=tr[x].son[k^1],tr[tr[x].son[k^1]].fa=y;tr[x].son[k^1]=y,tr[y].fa=x;pushup(y),pushup(x);
}
inline void splay(int x,int goal){while(tr[x].fa!=goal){int y=tr[x].fa,z=tr[y].fa;if(z!=goal)tr[y].son[1]==x^tr[z].son[1]==y?rotate(x):rotate(y);rotate(x);}if(!goal)root=x;
}
inline int ask(int u,int rank){pushdown(u);if(tr[tr[u].son[0]].siz>=rank)return ask(tr[u].son[0],rank);else if(tr[tr[u].son[0]].siz+1==rank)return u;else return ask(tr[u].son[1],rank-tr[tr[u].son[0]].siz-1);
}
inline void print(int u){pushdown(u);if(tr[u].son[0])print(tr[u].son[0]);if(tr[u].val>=1&&tr[u].val<=n)printf("%d ",tr[u].val);if(tr[u].son[1])print(tr[u].son[1]);
}
int main(){scanf("%d%d",&n,&m);root=build(0,n+1,0);while(m--){int l,r;scanf("%d%d",&l,&r);l=ask(root,l);r=ask(root,r+2);splay(l,0);splay(r,l);if(tr[r].son[0])tr[tr[r].son[0]].tag^=1;}print(root);return 0;
}