AC日记——文艺平衡树 洛谷 P3391

Posted Only U - IU

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AC日记——文艺平衡树 洛谷 P3391相关的知识,希望对你有一定的参考价值。

文艺平衡树

 

思路:

  splay翻转操作模板;

  虚拟最左最右端点,然后每次都把l翻转到root,r+2翻转到root的右节点;

  然后在r+2的左节点上打标记;

  标记需要在旋转,rank,print时下放;

  建树需要用完全平衡二叉树;

 

来,上代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define maxn 100005

struct TreeNodeType {
    int key,opi,size,ch[2],flag;
};
struct TreeNodeType tree[maxn];

int n,m,root,ans[maxn],tot;

inline void in(int &now)
{
    register char Cget=getchar();now=0;
    while(Cget>9||Cget<0) Cget=getchar();
    while(Cget>=0&&Cget<=9)
    {
        now=now*10+Cget-0;
        Cget=getchar();
    }
}

inline void updata(int now)
{
    tree[now].size=1;
    if(tree[now].ch[0]) tree[now].size+=tree[tree[now].ch[0]].size;
    if(tree[now].ch[1]) tree[now].size+=tree[tree[now].ch[1]].size;
}

inline void down(int now)
{
    tree[now].flag=0;
    swap(tree[now].ch[0],tree[now].ch[1]);
    if(tree[now].ch[0]) tree[tree[now].ch[0]].flag^=1;
    if(tree[now].ch[1]) tree[tree[now].ch[1]].flag^=1;
}

inline int getson(int now)
{
    return tree[tree[now].opi].ch[1]==now;
}

void rotate(int now)
{
    int opi=tree[now].opi,fopi=tree[opi].opi,pos=getson(now);
    if(tree[opi].flag&&opi) down(opi);
    if(tree[now].flag&&now) down(now);
    tree[opi].ch[pos]=tree[now].ch[!pos];
    tree[tree[now].ch[!pos]].opi=opi;
    tree[now].ch[!pos]=opi;
    tree[opi].opi=now;
    tree[now].opi=fopi;
    if(fopi) tree[fopi].ch[tree[fopi].ch[1]==opi]=now;
    updata(opi),updata(now);
}

inline void splay(int now,int to)
{
    for(int opi;(opi=tree[now].opi)!=to;rotate(now))
    {
        if(tree[opi].opi!=to) rotate(getson(now)==getson(opi)?opi:now);
    }
    if(!to) root=now;
}

int rank_(int x)
{
    int now=root;
    while(1)
    {
        if(tree[now].flag) down(now);
        if(tree[tree[now].ch[0]].size>=x) now=tree[now].ch[0];
        else
        {
            x-=tree[tree[now].ch[0]].size+1;
            if(!x) return now;
            now=tree[now].ch[1];
        }
    }
}

void print(int now)
{
    if(tree[now].flag) down(now);
    if(tree[now].ch[0]) print(tree[now].ch[0]);
    ans[++tot]=tree[now].key;
    if(tree[now].ch[1]) print(tree[now].ch[1]);
}

int build(int l,int r,int opi)
{
    int now=(l+r)>>1;
    tree[now].opi=opi;
    tree[now].key=ans[now];
    if(now>l) tree[now].ch[0]=build(l,now-1,now);
    if(now<r) tree[now].ch[1]=build(now+1,r,now);
    updata(now);return now;
}

int main()
{
    in(n),in(m),root=1;
    for(int i=1;i<=n+2;i++) ans[i]=i-1;
    root=build(1,n+2,0);
    int l,r;
    while(m--)
    {
        in(l),in(r);
        l,r+=2;
        int x=rank_(l),y=rank_(r);
        splay(x,0);
        splay(y,x);
        tree[tree[tree[root].ch[1]].ch[0]].flag^=1;
    }
    print(root);
    for(int i=1;i<=n;i++) printf("%d ",ans[i+1]);
    return 0;
}

 

以上是关于AC日记——文艺平衡树 洛谷 P3391的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P3391 模板文艺平衡树(Splay)

洛谷P3391 模板文艺平衡树(Splay)(FHQ Treap)

洛谷 P3391 模板文艺平衡树(Splay)

P3391 模板文艺平衡树(Splay)

P3391 模板文艺平衡树(Splay)新板子

[luogu P3391] 文艺平衡树