您的位置:首页 > 其它

【bzoj3223】Tyvj 1729 文艺平衡树 Splay

2015-12-08 20:10 281 查看

Description

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1

Input

第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n) m表示翻转操作次数

接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n

Output

输出一行n个数字,表示原始序列经过m次变换后的结果

Sample Input

[code]5 3

1 3

1 3

1 4


Sample Output

[code]4 3 2 1 5


HINT

N,M<=100000

Source

平衡树

splay区间操作,蛋疼了我半天…………

每个节点存儿子、父亲、出现次数、子树大小、权值。其中权值为该节点代表的序列的位置的那个值。

权值并不用来维护平衡树的性质,维护平衡树的性质的那个权值(也就是下标)并不存下来。旋转并不会破坏这个性质。

这样就可以像寻找第K大那样找到序列中某一个点了。

翻转区间:交换左右儿子的指针。

代码:

[code]#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

const int SZ = 1000010;
const int INF = 1000000010;

struct node{
    node *ch[2],*f;
    int sz,cnt,v,x;
    bool flag;

    void maintain() { sz = ch[0] -> sz + ch[1] -> sz + cnt; }

    void setc(node *x,int d) { (ch[d] = x) -> f = this; }

    int cmp(int x)
    {
        if(x == v) return -1;
        return x < v ? 0 : 1;
    }

    int dir() { return f -> ch[1] == this; }

    void pushdown();

}T[SZ], *root, *null;

int Tcnt = 0;

void node::pushdown()
{
    if(flag)
    {
        flag = 0;
        if(ch[1] != null) ch[1] -> flag ^= 1;
        if(ch[0] != null) ch[0] -> flag ^= 1;
        swap(ch[0],ch[1]);
    }
}

node* newnode(int v,node *f)
{
    node *k = T + (Tcnt ++);
    k -> ch[1] = k -> ch[0] = null;
    k -> v = v;
    k -> sz = k -> cnt = 1;
    k -> flag = 0;
    k -> f = f;
    return k;
}

void rotate(node *p)
{
    p -> f -> pushdown();   p -> pushdown();
    node *fa = p -> f;
    int d = p -> dir();
    fa -> f -> setc(p,fa -> dir());
    fa -> setc(p -> ch[d ^ 1],d); fa -> maintain();
    p -> setc(fa,d ^ 1); p -> maintain();
    if(fa == root) root = p;
}

void splay(node *p,node *rt = null)
{
    while(p -> f != rt)
    {
        p -> pushdown();
        if(p -> f -> f == rt) rotate(p);
        else
        {
            if(p -> dir() == p -> f -> dir()) rotate(p -> f),rotate(p);
            else rotate(p),rotate(p);
        }
    }
}

node* find(node *p,int k)
{
    while(p != null)
    {
        p -> pushdown();
        int l = p -> ch[0] -> sz + 1;
        int r = p -> ch[0] -> sz + p -> cnt;
        if(l <= k && k <= r) return p;
        if(k > r) k -= r,p = p -> ch[1];
        else p = p -> ch[0];
    }
}

void reverse(node *p,int l,int r)
{
    l ++; r ++;
    node* pre = find(root,l - 1);
    node* suf = find(root,r + 1);
    splay(pre); splay(suf,root);
    root -> ch[1] -> ch[0] -> flag ^= 1;
}

void build(node* &p,int l,int r,node *fa)
{
    if(l > r) return ;
    int mid = (l + r) >> 1;
    p = newnode(mid,fa);
    build(p -> ch[0],l,mid - 1,p);
    build(p -> ch[1],mid + 1,r,p);
    p -> maintain();
}

int n,m;

void init()
{
    null = newnode(-INF,null);
    null -> sz = null -> cnt = 0;

    root = newnode(-INF,null);
    root -> ch[1] = newnode(INF,root);
    build(root -> ch[1] -> ch[0],1,n,root -> ch[1]);
    root -> ch[1] -> maintain();
    root -> maintain();
}

int main()
{
    scanf("%d%d",&n,&m);
    init();
    while(m --)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        reverse(root,l,r);
    }
    for(int i = 1;i <= n;i ++)
        printf("%d ",(find(root,i + 1)) -> v);
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: