链接
http://www.lydsy.com/JudgeOnline/problem.php?id=3223
题解
毒瘤平衡树害我调两节课。
那道“普通平衡树”到最后也没调过,只好转战这道“文艺平衡树”。
就是裸题啦..直接打标记就好,注意一开始建树的时候不要顺序插入否则会T飞..我是这样加:1、N、2、N-1….
中序遍历输出结果就好啦
代码
//splay
#include <cstdio>
#include <algorithm>
#define maxn 200000
using namespace std;
int N, M, ndtot;
struct node
{
int w, rev, size;
node *f, *ch[2];
}pool[maxn], *RT, *MIN, *MAX;
int read(int x=0)
{
char c=getchar();
while(c<48 or c>57)c=getchar();
while(c>=48 and c<=57)x=(x<<1)+(x<<3)+c-48, c=getchar();
return x;
}
inline int getwh(node *x){if(x->f->ch[0]==x)return 0;return 1;}
inline void rev(node *x){if(x)x->rev^=1;}
inline int size(node *x){if(x)return x->size;return 0;}
inline void join(node *x, node *y, int wh){if(x)x->f=y;if(y)y->ch[wh]=x;}
inline void pushdown(node *x)
{
if(x->rev)
{
swap(x->ch[0],x->ch[1]);
rev(x->ch[0]),rev(x->ch[1]);
x->rev=0;
}
}
inline void pushup(node *x){x->size=size(x->ch[0])+size(x->ch[1])+1;}
inline void rot(node *x)
{
node *y=x->f, *z=y->f; int c=getwh(x);
pushdown(y), pushdown(x);
join(x,z,getwh(y)), join(x->ch[!c],y,c), join(y,x,!c);
pushup(y), pushup(x);
}
inline void splay(node *x, node *rt)
{
node *y;
while(x->f!=rt)
{
y=x->f;
if(y->f==rt){rot(x);return;}
if(getwh(x)^getwh(y))rot(x);else rot(y); rot(x);
}
}
void ins(node *x, node *t)
{
int wh=x->w<t->w;
if(x->ch[wh])ins(x->ch[wh],t);
else
{
join(t,x,wh);
for(;x!=RT;x=x->f)pushup(x);
}
}
node* find(node *x, int k)
{
pushdown(x);
if(k<=size(x->ch[0]))return find(x->ch[0],k);
if(k==size(x->ch[0])+1)return x;
return find(x->ch[1],k-size(x->ch[0])-1);
}
void dfs(node *x)
{
if(!x)return;
pushdown(x);
dfs(x->ch[0]);
if(x-pool>3)printf("%d ",x->w);
dfs(x->ch[1]);
}
int main()
{
int i, l, r; node *p, *L, *R;
N=read(), M=read();
RT=pool+ ++ndtot; RT->w=0x7fffffff;
MIN=pool+ ++ndtot; MIN->w=-1, MIN->size=1;
MAX=pool+ ++ndtot; MAX->w=0x7fffffff-1, MAX->size=1;
ins(RT,MIN), ins(RT, MAX);
for(i=1;i<=N-i+1;i++)
{
p=pool+ ++ndtot;
p->size=1, p->w=i;
ins(RT,p),splay(p,RT);
if(i==N-i+1)break;
p=pool+ ++ndtot;
p->size=1, p->w=N-i+1;
ins(RT,p),splay(p,RT);
}
for(i=1;i<=M;i++)
{
l=read()+1, r=read()+1;
L=find(RT,l-1), R=find(RT,r+1);
splay(L,RT), splay(R,L);
rev(R->ch[0]);
}
dfs(RT);
return 0;
}
本文介绍了一道名为“文艺平衡树”的ACM题目,通过使用旋转平衡树(Splay Tree)解决该问题。文章提供了详细的代码实现,并强调了在建立平衡树时避免顺序插入的重要性。

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



