bzoj3223: Tyvj 1729 文艺平衡树

本文介绍了一道名为“文艺平衡树”的ACM题目,通过使用旋转平衡树(Splay Tree)解决该问题。文章提供了详细的代码实现,并强调了在建立平衡树时避免顺序插入的重要性。

链接

  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;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值