P3391 模板文艺平衡树(Splay)
Posted driverben
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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]数据保证1≤l≤r≤n 1
输出格式:输出一行n个数字,表示原始序列经过m次变换后的结果
输入输出样例
输入样例#1:
5 3 1 3 1 3 1 4
输出样例#1:
4 3 2 1 5
说明
n,m≤100000
代码
将l-1和r+1分别旋转到根节点和根节点右儿子处,那么r+1的左子树即是区间[l,r]。
在其根处打上标记然后在查询k大和输出中序遍历时下传标记即可。
#include<bits/stdc++.h> using namespace std; const int maxn=100000+100; int ch[maxn][2],size[maxn],cnt[maxn],val[maxn],fa[maxn],rev[maxn]; int root,ncnt; int n,m; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();} return x*f; } inline void swap(int& x,int&y) { x^=y,y^=x,x^=y; } inline void pushup(int u) { size[u]=size[ch[u][0]]+size[ch[u][1]]+cnt[u]; } inline void pushdown(int u) { if(rev[u]) { rev[ch[u][0]]^=1; rev[ch[u][1]]^=1; swap(ch[u][0],ch[u][1]); rev[u]^=1; } } inline int chk(int u) { return ch[fa[u]][1]==u; } void rotate(int u) { int f=fa[u],ff=fa[f],k=chk(u),s=ch[u][k^1]; ch[f][k]=s,fa[s]=f; ch[ff][chk(f)]=u,fa[u]=ff; ch[u][k^1]=f,fa[f]=u; pushup(u),pushup(f); } void splay(int u,int goal=0) { while(fa[u]!=goal) { int f=fa[u],ff=fa[f]; if(ff!=goal) { if(chk(u)==chk(f))rotate(f); else rotate(u); } rotate(u); } if(!goal)root=u; } void insert(int x) { int u=root,f=0; while(u&&val[u]!=x) f=u,u=ch[u][x>val[u]]; if(u)cnt[u]++; else { u=++ncnt; if(f)ch[f][x>val[f]]=u; fa[u]=f,val[u]=x; cnt[u]=size[u]=1; ch[u][0]=ch[u][1]=0; } splay(u); } int kth(int k) { int u=root; while(1) { pushdown(u); if(ch[u][0]&&k<=size[ch[u][0]]) u=ch[u][0]; else if(k>size[ch[u][0]]+cnt[u]) k-=size[ch[u][0]]+cnt[u],u=ch[u][1]; else return u; } } void reverse(int l,int r) { int x=kth(l),y=kth(r+2); splay(x),splay(y,x); rev[ch[y][0]]^=1; } void output(int u) { pushdown(u); if(ch[u][0])output(ch[u][0]); if(val[u]&&val[u]<=n)printf("%d ",val[u]); if(ch[u][1])output(ch[u][1]); } int main() { n=read(),m=read(); for(int i=0;i<=n+1;i++)insert(i); for(int i=1;i<=m;i++) { int x=read(),y=read(); reverse(x,y); } output(root); return 0; }
以上是关于P3391 模板文艺平衡树(Splay)的主要内容,如果未能解决你的问题,请参考以下文章