Description
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1
N,M<=100000
Solution
裸的splay区间翻转,但是我不会╮(╯▽╰)╭
为了能区间操作我们需要按照下标为关键字建一棵splay,区间翻转(l,r)就把l-1旋到根,r+1旋到根的右儿子,这样r+1的左儿子就是我们要操作的区间了,像线段树一样打lazy即可
下传翻转的操作就是交换左右子树,注意深度较浅的节点先被下传,同理深度较深的节点先被上传更新
感觉这样splay和rotate操作简短一些,好记
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))
const int N=400005;
int son[N][2],fa[N],size[N],lazy[N],val[N];
int root=0,cnt=0;
int n,m;
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void push_up(int x) {size[x]=size[son[x][0]]+size[son[x][1]]+1;}
void push_down(int x) {
if (!lazy[x]) return ;
lazy[son[x][0]]^=1; lazy[son[x][1]]^=1;
std:: swap(son[x][0],son[x][1]);
lazy[x]=0;
}
void rotate(int x) {
int y=fa[x]; int z=fa[y];
int k=son[y][1]==x;
son[z][son[z][1]==y]=x;
fa[x]=z;
son[y][k]=son[x][k^1];
fa[son[x][k^1]]=y;
son[x][k^1]=y;
fa[y]=x;
push_up(y); push_up(x);
}
void splay(int x,int goal) {
while (fa[x]!=goal) {
int y=fa[x]; int z=fa[y];
if (z!=goal) {
if ((son[z][1]==y)^(son[y][1]==x)) rotate(x);
else rotate(y);
}
rotate(x);
}
if (!goal) root=x;
}
void insert(int v) {
int x=root,father=0;
while (x) father=x,x=son[x][v>val[x]];
x=++cnt; fa[x]=father; val[x]=v; size[x]=1;
if (father) son[father][v>val[father]]=x;
splay(x,0);
}
int query(int k) {
int x=root;
while (233) {
push_down(x);
if (size[son[x][0]]>=k) x=son[x][0];
else if (size[son[x][0]]+1==k) return x;
else k-=size[son[x][0]]+1,x=son[x][1];
}
}
void output(int x) {
push_down(x);
if (son[x][0]) output(son[x][0]);
if (val[x]>1&&val[x]<n+2) printf("%d ", val[x]-1);
if (son[x][1]) output(son[x][1]);
}
void reverse(int l,int r) {
l=query(l);
r=query(r+2);
splay(l,0); splay(r,l);
lazy[son[son[root][1]][0]]^=1;
}
int main(void) {
n=read(),m=read();
rep(i,1,n+2) {
insert(i);
}
while (m--) {
int l=read(),r=read();
reverse(l,r);
}
output(root);
return 0;
}

本文介绍了一种基于Splay树实现区间翻转的数据结构,适用于动态维护有序数列并进行区间翻转操作。通过旋转操作调整树结构,实现区间翻转功能。
1万+

被折叠的 条评论
为什么被折叠?



