洛谷 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
splay区间操作
把l-1旋到根,r+1旋到右节点,打上flag标记。
#include <algorithm> #include <ctype.h> #include <cstdio> #define INF 0x7fffffff #define N 100010 using namespace std; inline void read(int &x) { x=0;bool f=0; register char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=1; for(; isdigit(ch);ch=getchar()) x=(x<<3)+(x<<1)+ch-'0'; x=f?(~x)+1:x; } struct node { int data,pos; bool operator<(node a)const { if(data==a.data) return pos<a.pos; return data<a.data; } }d[N]; int data[N],flag[N],ch[N][2],fa[N],siz[N],root,n,m,cn,mn[N],pos[N]; inline int min(int a,int b) {return a>b?b:a;} inline void pushup(int x) { mn[x]=min(data[x],min(mn[ch[x][0]],mn[ch[x][1]])); if(mn[x]==data[x]) pos[x]=x; else if(mn[x]==mn[ch[x][0]]) pos[x]=pos[ch[x][0]]; else pos[x]=pos[ch[x][1]]; siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1; } inline void pushdown(int x) { if(flag[x]) { flag[x]=0; flag[ch[x][0]]^=1; swap(ch[ch[x][0]][0],ch[ch[x][0]][1]); flag[ch[x][1]]^=1; swap(ch[ch[x][1]][0],ch[ch[x][1]][1]); } } inline int son(int x) {return ch[fa[x]][1]==x;} int getkth(int rt,int k) { pushdown(rt); int l=ch[rt][0]; if(siz[l]+1==k) return rt; if(k<siz[l]+1) return getkth(ch[rt][0],k); return getkth(ch[rt][1],k-(siz[l]+1)); } inline void rotate(int x) { int y=fa[x],z=fa[y],b=son(x),c=son(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; pushup(y);pushup(x); } void splay(int x,int i) { while(fa[x]!=i) { int y=fa[x],z=fa[y]; if(z==i) rotate(x); else { pushdown(z); pushdown(y); pushdown(x); if(son(x)==son(y)) { rotate(y); rotate(x); } else { rotate(x); rotate(x); } } } } void reverse(int l,int r) { int ll=getkth(root,l-1),rr=getkth(root,r+1); splay(ll,0); splay(rr,ll); int p=ch[rr][0]; flag[p]^=1; swap(ch[p][0],ch[p][1]); } void dfs(int x) { if(!x) return; pushdown(x); dfs(ch[x][0]); if(x>1&&x<n+2) printf("%d ",data[x]-1); dfs(ch[x][1]); } int main() { read(n); read(m); for(int i=2;i<=n+1;i++) { data[i]=i-1; d[i].data=i-1; d[i].pos=i; } sort(d+2,d+2+n); for(int i=2;i<=n+1;i++) data[d[i].pos]=i; data[0]=data[1]=data[n+2]=INF; for(int i=0;i<=n+2;i++) mn[i]=INF; root=1; siz[0]=0; for(int i=1;i<=n+2;i++) { fa[i]=i-1; ch[i][1]=i+1; } ch[n+2][1]=0; for(int i=n+2;i>=1;i--) pushup(i); for(int l,r,i=1;i<=m;i++) { read(l); read(r); reverse(l+1,r+1); } dfs(root); return 0; }
我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。