zoukankan      html  css  js  c++  java
  • [HNOI2004]宠物收养场 Treap前驱后继

    凡凡开了一间宠物收养场。收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物。
    每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领养的宠物的特点值a(a是一个正整数,a<2^31),而他也给每个处在收养场的宠物一个特点值。这样他就能够很方便的处理整个领养宠物的过程了,宠物收养场总是会有两种情况发生:被遗弃的宠物过多或者是想要收养宠物的人太多,而宠物太少。
    被遗弃的宠物过多时,假若到来一个领养者,这个领养者希望领养的宠物的特点值为a,那么它将会领养一只目前未被领养的宠物中特点值最接近a的一只宠物。(任何两只宠物的特点值都不可能是相同的,任何两个领养者的希望领养宠物的特点值也不可能是一样的)如果有两只满足要求的宠物,即存在两只宠物他们的特点值分别为a-b和a+b,那么领养者将会领养特点值为a-b的那只宠物。
    收养宠物的人过多,假若到来一只被收养的宠物,那么哪个领养者能够领养它呢?能够领养它的领养者,是那个希望被领养宠物的特点值最接近该宠物特点值的领养者,如果该宠物的特点值为a,存在两个领养者他们希望领养宠物的特点值分别为a-b和a+b,那么特点值为a-b的那个领养者将成功领养该宠物。
    一个领养者领养了一个特点值为a的宠物,而它本身希望领养的宠物的特点值为b,那么这个领养者的不满意程度为abs(a-b)。
    你得到了一年当中,领养者和被收养宠物到来收养所的情况,请你计算所有收养了宠物的领养者的不满意程度的总和。这一年初始时,收养所里面既没有宠物,也没有领养者。

    输入

    从文件input.txt中读入数据。文件的第一行为一个正整数n,n<=80000,表示一年当中来到收养场的宠物和领养者的总数。接下来的n行,按到来时间的先后顺序描述了一年当中来到收养场的宠物和领养者的情况。每行有两个正整数a, b,其中a=0表示宠物,a=1表示领养者,b表示宠物的特点值或是领养者希望领养宠物的特点值。(同一时间呆在收养所中的,要么全是宠物,要么全是领养者,这些宠物和领养者的个数不会超过10000个)

    输出

    输出文件output.txt中仅有一个正整数,表示一年当中所有收养了宠物的领养者的不满意程度的总和mod 1000000以后的结果。

    样例输入

    5 0 2 0 4 1 3 1 2 1 5

    样例输出

    3

    提示

    abs(3-2) + abs(2-4)=3,

    最后一个领养者没有宠物可以领养。

    题解:

    裸的Treap找前驱后继,本蒟蒻开了两个平衡树,如果宠物Treap为空就在人的Treap里插人,人的Treap就在宠物的Treap里插宠物。

    加一些判断再套个模版就ok了.

    具体看代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<ctime>
    #include<cstdlib>
    using namespace std;
    typedef long long ll;
    const int mod=1000000;
    const int N=80005;
    struct node
    {
        node *child[2];
        int x,lev;
    }a[N];
    node *pos,*root[2];
    int size[2];ll ans=0;
    int gi()
    {
        int str=0;char ch=getchar();
        while(ch>'9'||ch<'0')ch=getchar();
        while(ch>='0' && ch<='9')str=str*10+ch-'0',ch=getchar();
        return str;
    }
     
    void newnode(node *&r,int key)
    {
        r=pos++;
        r->child[1]=r->child[0]=NULL;
        r->lev=rand();
        r->x=key; 
    }
    int pre,nxt;
    void rotate(node *&r,bool t)//0 ->left 1 ->right
    {
        node *y=r->child[!t];
        r->child[!t]=y->child[t];
        y->child[t]=r;
        r=y;
    }
    void insert(node *&r,int key)
    {
        if(r==NULL){newnode(r,key);return;}
        bool t=r->x<key;
        insert(r->child[t],key);
        if(r->child[t]->lev>r->lev)rotate(r,!t);
    }
    void getspre(node *&r,int key)
    {
        if(r==NULL)return ;
        if(r->x>key)getspre(r->child[0],key);
        else pre=r->x,getspre(r->child[1],key);
    }
     
    void getnext(node *&r,int key)
    {
        if(r==NULL)return ;
        if(r->x<key)getnext(r->child[1],key);
        else nxt=r->x,getnext(r->child[0],key);
    }
     
    void Delet(node *&r,int key)
    {
        if(r==NULL)return ;
        if(r->x==key)
        {
            if(r->child[0] && r->child[1])
            {
                bool t=r->child[0]->lev<r->child[1]->lev;
                rotate(r,t);
                Delet(r->child[t],key);
            }
            else
            {
                if(r->child[0])r=r->child[0];
                else r=r->child[1];
            }
        }
        else Delet(r->child[key>r->x],key);
    }
    int main()
    {
        pos=a;
        int n,x,y;
        n=gi();
        for(int i=1;i<=n;i++)
        {
            x=gi();y=gi();
            if(size[!x]==0)
            {
                size[x]++;
                insert(root[x],y);
            }
            else
            {
                pre=nxt=-1;
                getnext(root[!x],y);getspre(root[!x],y);
                size[!x]--;
                if(pre!=-1 && nxt!=-1)
                {
                    if(y-pre<=nxt-y){
                        ans+=y-pre;ans%=mod;
                        Delet(root[!x],pre);
                    }
                    else{
                        ans+=nxt-y;ans%=mod;
                        Delet(root[!x],nxt);
                    }
                }
                else
                {
                    if(pre!=-1){
                        ans+=y-pre;ans%=mod;
                        Delet(root[!x],pre);
                    }
                    else{
                        ans+=nxt-y;ans%=mod;
                        Delet(root[!x],nxt);
                    }
                }
            }
        }
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    无旋转Treap简介
    bzoj 4318 OSU!
    bzoj 1419 Red is good
    bzoj 4008 亚瑟王
    bzoj 1014 火星人prefix
    更多的莫队
    bzoj 3489 A simple rmq problem
    洛谷 2056 采花
    NOIP 2017 游(划水)记
    UVa 11997 K Smallest Sums
  • 原文地址:https://www.cnblogs.com/Yuzao/p/6761801.html
Copyright © 2011-2022 走看看