首页 > 其他 > 详细

HNOI2004 宠物收养场 [Treap]

时间:2018-01-14 00:24:54      阅读:99      评论:0      收藏:0      [点我收藏+]

标签:amp   -i   后继   是否   不能   while   clas   min   const   

题面传送门戳我

Treap计算前驱/后继。

直接搞两个Treap,一个维护宠物,一个维护收养人。

如果输入人,并且宠物Treap不为空,直接查询一下,然后删除。否则插入人Treap。

宠物同理。

但是在查询Treap是否为空的时候不能直接写if(root[x]->size==0)因为这个时候有可能Treap为空,就会RE。

所以要这么写if(root[x]==NULL || root[x]->size==0),因为if语句有个机制,它会先判断前面的条件,如果前面的条件满足就不会去判断后面的。。。

#include <bits/stdc++.h>

const int inf=0x3f3f3f3f;
const int mod=1000000;

int N,Ans;

struct Treap
{
    Treap *ch[2];
    int r,v,size;
    Treap(int x)
    {
        v=x;
        r=rand();
        size=1;
        ch[0]=ch[1]=NULL;
    }
    int cmp(int x)
    {
        if(x==v) return -1;
        return x>v; 
    }   
    void maintain()
    {
        size=1+((ch[0]==NULL)?0:ch[0]->size)+((ch[1]==NULL)?0:ch[1]->size);
    }
}*root[2];

void rotate(Treap* &o,int d)
{
    Treap *k=o->ch[d^1];
    o->ch[d^1]=k->ch[d];
    k->ch[d]=o;
    o->maintain(),k->maintain();
    o=k;
}

void insert(Treap* &o,int x)
{
    if(o==NULL) o=new Treap(x);
    else
    {
        int d=o->cmp(x);
        insert(o->ch[d],x);
        if(o->ch[d]->r>o->r) rotate(o,d^1); 
    }
    o->maintain();
}

void remove(Treap* &o,int x)
{
    int d=o->cmp(x);
    if(d==-1)
    {
        if(o->ch[0]==NULL) o=o->ch[1];
        else if(o->ch[1]==NULL) o=o->ch[0];
        else
        {
            int d2=o->ch[0]->r>o->ch[1]->r;
            rotate(o,d2);
            remove(o->ch[d2],x);
        }
    }
    else remove(o->ch[d],x);
    if(o!=NULL) o->maintain();
}

int upper(Treap *o,int x)
{
    if(o==NULL) return -inf;
    if(o->cmp(x)<=0) return upper(o->ch[0],x);
    else return std::max(o->v,upper(o->ch[1],x));
}

int lower(Treap *o,int x)
{
    if(o==NULL) return inf;
    if(o->cmp(x)) return lower(o->ch[1],x);
    else return std::min(o->v,lower(o->ch[0],x));
} 

inline int read()
{
    register int x=0;
    register char ch=getchar();
    while(!isdigit(ch))
        ch=getchar();
    while(isdigit(ch))
    {
        x=(x<<1)+(x<<3)+ch-‘0‘;
        ch=getchar();
    }
    return x;
}

int main()
{
    int x,y,upp,low;
    N=read();
    for(register int i=1;i<=N;++i)
    {
        x=read(),y=read();
        if(root[x^1]==NULL || root[x^1]->size==0) insert(root[x],y);
        else
        {
            upp=upper(root[x^1],y),low=lower(root[x^1],y);
            if(upp!=-inf && low!=inf)
            {
                if(y-upp<=low-y)
                {
                    (Ans+=y-upp)%=mod;
                    remove(root[x^1],upp);
                }
                else
                {
                    (Ans+=low-y)%=mod;
                    remove(root[x^1],low);
                }
            }
            else
            {
                if(upp==-inf)
                {
                    (Ans+=low-y)%=mod;
                    remove(root[x^1],low);
                }   
                else
                {
                    (Ans+=y-upp)%=mod;
                    remove(root[x^1],upp);
                }
            } 
        }
    }
    printf("%d\n",Ans);
}

博主是蒟蒻,有错误请指出,谢谢!

HNOI2004 宠物收养场 [Treap]

标签:amp   -i   后继   是否   不能   while   clas   min   const   

原文:https://www.cnblogs.com/zcdhj/p/8280911.html

(0)
(0)
   
举报
评论 一句话评论(0
0条  
登录后才能评论!
© 2014 bubuko.com 版权所有 鲁ICP备09046678号-4
打开技术之扣,分享程序人生!
             

鲁公网安备 37021202000002号