洛谷P3369-----普通平衡树

洛谷上的一道splay水题

但是不知为何做了很长时间

甚至还动用了洛谷的样例,可以说是非常菜了

跟正常的splay模版一样

但是有点细节需要注意

求前驱和后缀的方式十分巧妙,但是必须要求的是如果一个元素没有了,就必须让他的节点消失,

而不是把个数改成0就可以了,否则找到的当前这个点如果没有个数的话,可能是不如左子树的元素的

还有注意不仅insert后要splay到根,query过后也要到跟,防止深度过长导致时间复杂度骤升

嗯,就是这样

顺带一提这次noip差点退役,最后好死赖活着想继续省选

现在估计是省选的人里面最菜的一个了,唉。。。。。。

继续努力吧

#include<bits/stdc++.h>
using namespace std;
const int base=1e7+7;
struct node
{
    node *son[2],*father;
    int size,num,cnt;
}pool[3200005],*tail=pool,*root,*zero;
int n,shu1,shu2,all;
void update(node *nd)
{
    nd->size=nd->son[0]->size+nd->son[1]->size+nd->cnt;
}
void rotate(node *nd)
{
    node *p=nd->father;
    node *pp=p->father;
    int r1=p->son[0]==nd;
    int r2=pp->son[1]==p;
    node *s=nd->son[r1];
    if(pp==zero) root=nd;
    else pp->son[r2]=nd;
    nd->father=pp;
    p->father=nd;
    nd->son[r1]=p;
    if(s!=zero) s->father=p;
    p->son[!r1]=s;
    update(p);
    update(nd);
}
void splay(node *nd,node *top)
{
    while(nd->father!=top)
    {
        node *p=nd->father;
        if(p->father==top)
        {
            rotate(nd);
        }
        else 
        {
            node *pp=p->father;
            if((pp->son[1]==p)==(p->son[1]==nd))
            {
                rotate(p);
                rotate(nd);
            }
            else 
            {
                rotate(nd);
                rotate(nd);
            }
        }
    }
}
void init()
{
    zero=tail++;
    zero->son[0]=zero->son[1]=zero->father=zero;
    root=tail++;
    root->son[0]=tail++;
    root->son[1]=zero;
    root->son[0]->son[0]=zero;
    root->son[0]->son[1]=zero;
    root->size=2;
    root->cnt=1;
    root->num=1e7+5;
    root->son[0]->size=1;
    root->son[0]->cnt=1;
    root->son[0]->num=-1e7-5;
    root->son[0]->father=root;
    root->father=zero;
}
node *find_pos(int x)
{
    node *pos=root;
    while(233)
    {
        if(x<pos->num) pos=pos->son[0];
        else if(x>pos->num) pos=pos->son[1];
        else return pos;
    }
}
node *find_num(int x)
{
    x++;
    node *pos=root;
    while(233)
    {
        if(x<=pos->son[0]->size) pos=pos->son[0];
        else if(x>pos->son[0]->size+pos->cnt) x-=pos->son[0]->size+pos->cnt,pos=pos->son[1];
        else return pos;
    }
}
void print(node *nd)
{
    if(nd==zero) return;
    print(nd->son[0]);
    for(int i=1;i<=nd->cnt;i++)
    printf("%d ",nd->num);
    print(nd->son[1]);
}
void insert(node *&nd,node *fa,int num)
{
    if(nd==zero)
    {
        nd=tail++;
        nd->father=fa;
        nd->son[0]=nd->son[1]=zero;
        nd->size=1;
        nd->cnt=1;
        nd->num=num;
        splay(nd,zero);
        return;
    }
    if(num<nd->num) insert(nd->son[0],nd,num);
    else if(num>nd->num) insert(nd->son[1],nd,num);
    else {nd->cnt++;nd->size++;return;}
    update(nd);
}
int query_pos(int x)
{
    node *pos=root;
    int ans=0;
    while(233)
    {
        if(x<pos->num) pos=pos->son[0];
        else if(x>pos->num) ans+=pos->size-pos->son[1]->size,pos=pos->son[1];
        else 
        {
            ans+=pos->son[0]->size;
            splay(pos,zero);
            return ans;
        }
    }
}
int query_num(int x)
{
    node *one=find_num(x);
    splay(one,zero);
    return one->num;
}
void dilit(int x)
{
    node *one=find_pos(x);
    if(one->cnt==1)
    {
        int two=query_pos(x);
        node *r1=find_num(two-1);
        node *r2=find_num(two+1);
        splay(r1,zero);
        splay(r2,r1);
        r2->son[0]=zero;
        one=zero;
        update(r2);
        update(r1);
    }
    else 
    {
        splay(one,zero);
        one->cnt--;
        one->size--;
    }
}
int pre(int x)
{
    int ans=-0x7fffffff;
    node *pos=root;
    while(233)
    {
        if(pos->num<x&&pos->num>ans&&pos->cnt) ans=pos->num;
        if(x>pos->num) pos=pos->son[1];
        else pos=pos->son[0];
        if(pos==zero) 
        {
            if(pos->father!=zero)
            splay(pos->father,zero);
            break;
        }
    }
    return ans;
}
int suf(int x)
{
    int ans=0x7fffffff;
    node *pos=root;
    while(233)
    {
        if(pos->num>x&&pos->num<ans&&pos->cnt) ans=pos->num;
        if(x<pos->num) pos=pos->son[0];
        else pos=pos->son[1];
        if(pos==zero) 
        {
            if(pos->father!=zero)
            splay(pos->father,zero);
            break;
        }
    }
    return ans;
}
int main()
{
    init();
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&shu1,&shu2);
        if(shu1==1)
        {
            insert(root,zero,shu2);
            all++;
        }
        else if(shu1==2)
        {
            dilit(shu2);
            all--;
        }
        else if(shu1==3)
        {
            printf("%d\n",query_pos(shu2));
        }
        else if(shu1==4)
        {
            printf("%d\n",query_num(shu2));
        }
        else if(shu1==5)
        {
            printf("%d\n",pre(shu2));
        }
        else if(shu1==6)
        {
            printf("%d\n",suf(shu2));
        }
    }
    return 0;
}
/*
4
1 2
2 2
1 2
3 2

*/

猜你喜欢

转载自blog.csdn.net/ENESAMA/article/details/84503196
今日推荐