【BZOJ3224】【codevs4543】【tyvj1728】普通平衡树,第一次的splay

传送门1
传送门2
传送门3
写在前面:woc……woc……大家知道为什么这么久没写题解了吧
思路:不会用指针千万别用!千万别手贱多写函数!千万多调用splay!
感谢http://blog.csdn.net/leolin_/article/details/6436037
http://codevs.cn/wiki/solution/?problem_id=4543
solution16851
注意:数组版splay,个人不喜欢压行,代码写了4k,个人感觉思路还是蛮清晰的,没有特别的技巧,不推荐作为模板使用
代码:

#include"bits/stdc++.h"
using namespace std;
int n,root,tot;
struct os
{
    int left,right,father,sz,occ,data;
}a[300000];
void ct(int root)
{
    a[root].sz=a[root].occ+a[a[root].left].sz+a[a[root].right].sz;
}
void made(int x)
{
    a[++tot].data=x;
    a[tot].sz=a[tot].occ=1;
}
void rotate(int x,bool flag)
{
    int y=a[x].father;
    if (flag)
    {
        a[y].left=a[x].right;
        if (a[x].right) a[a[x].right].father=y;
        a[x].father=a[y].father;
        if (a[y].father)
        {
            if (a[a[y].father].left==y)
            a[a[y].father].left=x;
            else a[a[y].father].right=x;
        }
        a[x].right=y;
        a[y].father=x;
    }
    else
    {
        a[y].right=a[x].left;
        if (a[x].left) a[a[x].left].father=y;
        a[x].father=a[y].father;
        if (a[y].father)
        {
            if (a[a[y].father].left==y)
            a[a[y].father].left=x;
            else a[a[y].father].right=x;
        }
        a[x].left=y;
        a[y].father=x;  
    }
    ct(y);
    ct(x);
}
void splay(int x,int goal)
{
    int y;
    while (a[x].father!=goal)
    {
        y=a[x].father;
        if (a[y].father==goal)
        {
            if (a[y].left==x) rotate(x,1);
            else rotate(x,0);
        }
        else if (a[a[y].father].left==y)
        {
            if (a[y].left==x) rotate(y,1);
            else rotate(x,0);
            rotate(x,1);
        }
        else
        {
            if (a[y].right==x) rotate(y,0);
            else rotate(x,1);
            rotate(x,0);
        }
    }
    if (!goal) root=x;
}
void insert(int now,int x)
{
    if (!root) {made(x);root=tot;return;}
    int flag=0;
    while (!flag)
    {
        a[now].sz++;
        if (a[now].data==x) a[now].occ++,flag=2;
        else if (a[now].data>x)
        {
            if (!a[now].left) made(x),a[now].left=tot,a[tot].father=now,flag=1;
            else now=a[now].left;
        }
        else
        {
            if (!a[now].right) made(x),a[now].right=tot,a[tot].father=now,flag=1;
            else now=a[now].right;
        }
    }
    splay((flag==1)?tot:now,0);
}
int find(int now,int x)
{
    while (now)
    {
        if (a[now].data==x) {splay(now,0);return now;}
        else if (a[now].data>x) now=a[now].left;
        else now=a[now].right;
    }
    return 0;
}
int find_max(int now)
{
    int pa=a[now].father;
    if (!now) return 0;
    while (a[now].right) now=a[now].right;
    splay(now,pa);
    return now;
}
int find_min(int now)
{
    int pa=a[now].father;
    if (!now) return 0;
    while (a[now].left) now=a[now].left;
    splay(now,pa);
    return now;
}
int find_next_min(int x)
{
    int ans=0,now=root;
    while (now)
    {
        if (a[now].data>=x) now=a[now].left;
        else ans=(a[now].data>a[ans].data||!ans)?now:ans,now=a[now].right;
    }
    splay(ans,0);
    return ans;
}
int find_next_max(int x)
{
    int ans=0,now=root;
    while (now)
    {
        if (a[now].data<=x) now=a[now].right;
        else ans=(a[now].data<a[ans].data||!ans)?now:ans,now=a[now].left;
    }
    splay(ans,0);
    return ans;
}
bool del(int x)
{
    int now=find(root,x);
    if (!now) return 0;
    splay(now,0);
    if (a[now].occ>1)
    {
        --a[now].occ;
        --a[now].sz;
        return 1;
    }
    if (!a[now].left&&!a[now].right) root=0;
    else if (!a[now].left)
    {
        root=a[now].right;
        a[a[now].right].father=0;
    }
    else if (!a[now].right)
    {
        root=a[now].left;
        a[a[now].left].father=0;
    }
    else
    {
        splay(find_max(a[now].left),root);
        a[a[now].left].right=a[now].right;
        a[a[now].right].father=a[now].left;
        a[a[now].left].father=0;
        root=a[now].left;
        ct(a[now].left);
    }
    ct(now);
    return 1;
}
int Kth(int k)
{
    int now=root;
    int p;
    while (now)
    {
        p=a[a[now].left].sz;
        if (k>p&&k<=p+a[now].occ) break;
        if (k<=p) now=a[now].left;
        else k-=(p+a[now].occ),now=a[now].right;
    }
    splay(now,0);
    return now;
}
int find_rank(int x)
{
    int ans=0,now=root;
    while (1)
    {
        if (x<a[now].data) now=a[now].left;
        else
        {
            if (x==a[now].data)
            {
                ans+=a[a[now].left].sz+1;
                break;
            }
            else ans+=a[a[now].left].sz+a[now].occ,now=a[now].right;
        }
    }
    splay(now,0);
    return ans;
}
main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        if (x==1) insert(root,y);
        else if (x==2) del(y);
        else if (x==3) printf("%d\n",find_rank(y));
        else if (x==4) printf("%d\n",a[Kth(y)].data);
        else if (x==5) printf("%d\n",a[find_next_min(y)].data);
        else if (x==6) printf("%d\n",a[find_next_max(y)].data);
    }
}

你可能感兴趣的:(【BZOJ3224】【codevs4543】【tyvj1728】普通平衡树,第一次的splay)