【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);
    }
}

UPD
2017.3.23
学习后缀平衡树时搞了一发treap

#include<cstdio>
#include<iostream>
#include<cstdlib>
#define ls(x) tr[x].ch[0]
#define rs(x) tr[x].ch[1]
#define son(x,y) tr[x].ch[y]
#define M 100005
using namespace std;
int n,m,seed,root,cnt;
int in()
{
    int t=0;char ch=getchar();bool f=0;
    while (ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') t=(t<<1)+(t<<3)+ch-48,ch=getchar();
    return f?-t:t;
} 
int ran()
{
    seed=seed^rand();
    seed^=(seed<<7);
    seed^=(seed>>3);
    return seed;
}
struct Treap{
    int key,fix,siz,occ,fa,ch[2];
    void build(int Fa,int val)
    {
        key=val;
        fa=Fa;
        fix=ran();
        siz=occ=1;
        ch[0]=ch[1]=0;
    }
}tr[M];
void count(int rt)
{
    tr[rt].siz=tr[ls(rt)].siz+tr[rs(rt)].siz+tr[rt].occ;
}
void rotate(int x,bool f)
{
    int y=tr[x].fa;
    son(y,!f)=son(x,f);
    if (son(x,f)) tr[son(x,f)].fa=y;
    tr[x].fa=tr[y].fa;
    if (tr[y].fa)
        if (ls(tr[y].fa)==y) ls(tr[y].fa)=x;
        else rs(tr[y].fa)=x;
    son(x,f)=y;
    tr[y].fa=x;
    count(y);
    count(x);
}
void insert(int rt,int val)
{
    if (tr[rt].key==val) ++tr[rt].occ,++tr[rt].siz;
    else if (tr[rt].key>val)
    {
        if (ls(rt))
            insert(ls(rt),val);
        else
            tr[ls(rt)=++cnt].build(rt,val);
        if (tr[ls(rt)].fix<tr[rt].fix)
        {
            if (!tr[rt].fa) root=ls(rt);
            rotate(ls(rt),1);
        }
    }
    else
    {
        if (rs(rt))
            insert(rs(rt),val);
        else
            tr[rs(rt)=++cnt].build(rt,val);
        if (tr[rs(rt)].fix<tr[rt].fix)
        {
            if (!tr[rt].fa) root=rs(rt);
            rotate(rs(rt),0);
        }
    }
    count(rt);
}
void del(int rt,int val)
{
    if (tr[rt].key==val)
    {
        if (tr[rt].occ>1) --tr[rt].occ,--tr[rt].siz;
        else if (!ls(rt)&&!rs(rt))
            if (!tr[rt].fa) root=0;
            else
            {
                if (rt==ls(tr[rt].fa)) ls(tr[rt].fa)=0;
                else rs(tr[rt].fa)=0;
            }
        else if (!ls(rt))
            if (!tr[rt].fa) root=rs(rt),tr[rs(rt)].fa=0;
            else
            {
                tr[rs(rt)].fa=tr[rt].fa;
                if (ls(tr[rt].fa)==rt) ls(tr[rt].fa)=rs(rt);
                else rs(tr[rt].fa)=rs(rt);
            }
        else if (!rs(rt))
            if (!tr[rt].fa) root=ls(rt),tr[ls(rt)].fa=0;
            else
            {
                tr[ls(rt)].fa=tr[rt].fa;
                if (ls(tr[rt].fa)==rt) ls(tr[rt].fa)=ls(rt);
                else rs(tr[rt].fa)=ls(rt);
            }
        else
        {
            bool f=(tr[ls(rt)].fix<tr[rs(rt)].fix);
            int y=son(rt,!f);
            if (!tr[rt].fa) root=y;
            rotate(y,f);
            del(rt,val);
            count(y);
        }
    }
    else
    {
        if (tr[rt].key<val) del(rs(rt),val);
        else del(ls(rt),val);
        count(rt); 
    }
}
int Rank(int val)
{
    int x=root,ans=0;
    for (;;)
        if (tr[x].key==val) return ans+tr[ls(x)].siz+1;
        else if (tr[x].key<val) ans+=tr[ls(x)].siz+tr[x].occ,x=rs(x);
        else x=ls(x);
}
int Kth(int k)
{
    int x=root;
    for (;;)
        if (tr[ls(x)].siz<k&&k<=tr[ls(x)].siz+tr[x].occ) return tr[x].key;
        else if (tr[ls(x)].siz>=k) x=ls(x);
        else k-=tr[ls(x)].siz+tr[x].occ,x=rs(x);
}
int Pre(int val)
{
    int x=root,ans=-1<<30;
    for (;x;)
        if (tr[x].key<val) ans=max(ans,tr[x].key),x=rs(x);
        else x=ls(x);
    return ans;
}
int Sub(int val)
{
    int x=root,ans=1<<30;
    for (;x;)
        if (tr[x].key>val) ans=min(ans,tr[x].key),x=ls(x);
        else x=rs(x);
    return ans;
}
main()
{
    srand(20170322);
    int opt,x;
    for (n=in();n;--n)
    {
        opt=in();x=in();
        if (opt==1)
        {
            if (!root) tr[root=++cnt].build(0,x);
            else insert(root,x);
        }
        else if (opt==2) del(root,x);
        else if (opt==3) printf("%d\n",Rank(x));
        else if (opt==4) printf("%d\n",Kth(x));
        else if (opt==5) printf("%d\n",Pre(x));
        else if (opt==6) printf("%d\n",Sub(x));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值