1. 程式人生 > >洛谷P2286 [HNOI2004]寵物收養場

洛谷P2286 [HNOI2004]寵物收養場

題目描述

凡凡開了一間寵物收養場。收養場提供兩種服務:收養被主人遺棄的寵物和讓新的主人領養這些寵物。

每個領養者都希望領養到自己滿意的寵物,凡凡根據領養者的要求通過他自己發明的一個特殊的公式,得出該領養者希望領養的寵物的特點值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)。

你得到了一年當中,領養者和被收養寵物到來收養所的情況,請你計算所有收養了寵物的領養者的不滿意程度的總和。這一年初始時,收養所裡面既沒有寵物,也沒有領養者。

輸入輸出格式

輸入格式:

第一行為一個正整數n,n<=80000,表示一年當中來到收養場的寵物和領養者的總數。接下來的n行,按到來時間的先後順序描述了一年當中來到收養場的寵物和領養者的情況。每行有兩個正整數a, b,其中a=0表示寵物,a=1表示領養者,b表示寵物的特點值或是領養者希望領養寵物的特點值。(同一時間呆在收養所中的,要麼全是寵物,要麼全是領養者,這些寵物和領養者的個數不會超過10000個)

輸出格式:

僅有一個正整數,表示一年當中所有收養了寵物的領養者的不滿意程度的總和mod 1000000以後的結果。

輸入輸出樣例

輸入樣例#1: 複製
5                  
0 2                      
0 4                         
1 3
1 2
1 5
輸出樣例#1: 複製
3
注:abs(3-2) + abs(2-4)=3,
最後一個領養者沒有寵物可以領養。

哎呀一不小心拿了個rank1還比第二快9倍呢:joy:

這道題目比較簡單

請選擇一種資料結構,

支援插入、

刪除、求前驅後繼

splay裸題

有一個小技巧:

在求前驅後繼的時候增加兩個哨兵節點

這樣就不會加爆了

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
const int MAXN=1e6+10;
const int mod=1000000;
const int INF=2*0x7ffffff;
inline char nc()
{
    static char buf[MAXN],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin))?EOF:*p1++;
}
inline int read()
{
    char c=nc();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
    while(c>='0'&&c<='9'){x=x*10+c-'0',c=nc();}
    return x*f;
}
int PetNum;
#define root tree[0].ch[1]
struct node
{
    int v,fa,ch[2],rec;
}tree[MAXN];

int tot,point;
bool ident(int x)
{
    return tree[tree[x].fa].ch[0]==x?0:1;
}
void connect(int x,int fa,int how)
{
    tree[x].fa=fa;
    tree[fa].ch[how]=x;
}
void rotate(int x)
{
    int Y=tree[x].fa;
    int R=tree[Y].fa;
    int Yson=ident(x);
    int Rson=ident(Y);
    int B=tree[x].ch[Yson^1];
    connect(B,Y,Yson);
    connect(Y,x,Yson^1);
    connect(x,R,Rson);
}
void splay(int x,int to)
{
    to=tree[to].fa;
    while(tree[x].fa!=to)
    {
        if(tree[tree[x].fa].fa==to) rotate(x);
        else if(ident(x)==ident(tree[x].fa)) rotate(tree[x].fa),rotate(x);
        else rotate(x),rotate(x);
    }
}
void newpoint(int x,int fa)
{
    tree[++tot].v=x;
    tree[tot].fa=fa;
    tree[tot].rec=1;
}
void insert(int x)
{
    point++;
    if(tot==0){newpoint(x,0);root=tot;return ;}
    int now=root;
    while(1)
    {
        if(tree[now].v==x)
        {
            tree[now].rec++;
            splay(now,root);
            return ;
        }
        int nxt=x<tree[now].v?0:1;
        if(!tree[now].ch[nxt])
        {
            newpoint(x,now);
            tree[now].ch[nxt]=tot;
            splay(tot,root);
            return ;
        }
        now=tree[now].ch[nxt];
    }
}
int lower(int x)
{
    int ans=-INF;
    int now=root;
    while(now)
    {
        if(tree[now].v<x)   ans=max(ans,tree[now].v);
        int nxt=x<tree[now].v?0:1;
        if(tree[now].ch[nxt]==0)    return ans;
        now=tree[now].ch[nxt];
    }
    return ans;
}
int upper(int x)
{
    int ans=INF;
    int now=root;
    while(now)
    {
        if(tree[now].v>x)   ans=min(ans,tree[now].v);
        int nxt=x<tree[now].v?0:1;
        if(tree[now].ch[nxt]==0)    return ans;
        now=tree[now].ch[nxt];
    }
}
int find(int x)
{
    int now=root;
    while(1)
    {
        if(tree[now].v==x)  {splay(now,root);return now;}
        int nxt=x<tree[now].v?0:1;
        if(!tree[now].ch[nxt])    return 0;
        now=tree[now].ch[nxt];
    }
}
void des(int x)
{
    tree[x].ch[0]=tree[x].ch[1]=tree[x].fa=tree[x].rec=tree[x].v=0;
    if(x==tot) tot--;
}
void dele(int x)
{
    int deal=find(x);
    if(!deal)   return ;
    point--;
    if(tree[deal].rec>1){tree[deal].rec--;return ;}
    if(!tree[deal].ch[0]) root=tree[deal].ch[1],tree[root].fa=0;
    else
    {
        int mxson=tree[deal].ch[0];
        while(tree[mxson].ch[1])    mxson=tree[mxson].ch[1];
        splay(mxson,tree[deal].ch[0]);
        connect(tree[deal].ch[1],mxson,1);
        connect(mxson,0,1);
    }
    des(deal);
}
int main()
{
    #ifdef WIN32
    freopen("a.in","r",stdin);
    #else
    #endif
    int n=read(),ans=0;
    while(n--)
    {
        int opt=read(),x=read();
        if(PetNum==0)    
        {
            insert(x);
            if(opt==0)    PetNum++;
            else PetNum--;
        }
        else if(PetNum>0)
        {
            if(opt==0)  insert(x),PetNum++;
            else 
            {
                int pre=lower(x);
                int lat=upper(x);
                if(abs(pre-x)<=abs(x-lat))    dele(pre),ans=(ans+abs(pre-x))%mod;
                else    dele(lat),ans=(ans+abs(lat-x))%mod;
                PetNum--;
            }
        }
        else
        {
            if(opt==1)  insert(x),PetNum--;
            else
            {
                int pre=lower(x);
                int lat=upper(x);
                if((abs(pre-x))<abs(x-lat))    dele(pre),ans=(ans+abs(pre-x))%mod;
                //這裡寫小於等於和小於一樣 
                else    dele(lat),ans=(ans+abs(lat-x))%mod;
                PetNum++;
            }
        }
    }
    printf("%d",ans);
}

相關推薦

P2286 [HNOI2004]寵物收養

題目描述 凡凡開了一間寵物收養場。收養場提供兩種服務:收養被主人遺棄的寵物和讓新的主人領養這些寵物。 每個領養者都希望領養到自己滿意的寵物,凡凡根據領養者的要求通過他自己發明的一個特殊的公式,得出該領養者希望領養的寵物的特點值a(a是一個正整數,a<2^31),而他也給每個處在收養場的寵物一個特點值

P2286 [HNOI2004]寵物收養

題意 per 應該 scan void 可用 play 一個 spl 第一次用set水splay好爽啊! 這道題很明顯,就是弄兩個平衡樹(一個也可以)。 進來一個人,就去另一邊找找前驅和後繼,優先找前驅,找個絕對值最小的配對走。 其實用一下set就可以了啊! 使用std:

1208. [HNOI2004]寵物收養【平衡樹-splay】

過程 處理 過多 前驅 順序 urn 想要 esc 相同 Description 最近,阿Q開了一間寵物收養所。收養所提供兩種服務:收養被主人遺棄的寵物和讓新的主人領養這些寵物。每個領養者都希望領養到自己滿意的寵物,阿Q根據領養者的要求通過他自己發明的一個特殊的公式,得出

[HNOI2004]寵物收養——treap

color root 他也 turn 練習題 ans 可能 輸入格式 style 凡凡開了一間寵物收養場。收養場提供兩種服務:收養被主人遺棄的寵物和讓新的主人領養這些寵物。 每個領養者都希望領養到自己滿意的寵物,凡凡根據領養者的要求通過他自己發明的一個特殊的公式,得出該領

HNOI2004 寵物收養

air oal ace second def ble ons push math 傳送門 這道題比上一道稍微復雜那麽一些……不過大體上還是很容易的! 沒有必要建立兩棵splay,一棵就夠了。我們可以記錄一下當前在收養場的情況,如果cnt>0說明寵物多,否則人多,然後挨

LG_2286_[HNOI2004]寵物收養

題目描述 凡凡開了一間寵物收養場。收養場提供兩種服務:收養被主人遺棄的寵物和讓新的主人領養這些寵物。 每個領養者都希望領養到自己滿意的寵物,凡凡根據領養者的要求通過他自己發明的一個特殊的公式,得出該領養者希望領養的寵物的特點值a(a是一個正整數,a<2^31),而他也給每個處在收養場的寵物一個特點值

[HNOI2004]寵物收養 BZOJ1208 splay tree

題目描述 凡凡開了一間寵物收養場。收養場提供兩種服務:收養被主人遺棄的寵物和讓新的主人領養這些寵物。 每個領養者都希望領養到自己滿意的寵物,凡凡根據領養者的要求通過他自己發明的一個特殊的公式,得出該領養者希望領養的寵物的特點值a(a是一個正整數,a<2^31),而他也給每個處在收養場的寵物

[luogu2286][HNOI2004]寵物收養【平衡樹】

int class 傳送門 get 快速 總結 noi tor www 【傳送門】 前言 這一篇題解並不是為了講什麽算法,只是總結一下平衡樹在OI考試中的註意事項。 題意簡化(給不想看題目的小夥伴們一點福利) 給你兩堆數,每一次給你一個數,每一次在另外一堆數中找到這個數的前

[HNOI2004]寵物收養

直接插入 正整數 getc www. 選擇 初始 bits 也有 noi 洛咕 題意:寵物收養場提供兩種服務:收養被主人遺棄的寵物和讓新的主人領養這些寵物.每個領養者都希望領養到自己滿意的寵物,每個領養者希望領養的寵物的特點值為a(a是一個正整數,a<2^31),而每

題解 [HNOI2004]寵物收養

build val mes 同一時間 重復 == %d 解析 fin 解析 這題似乎是裸的平衡樹\(+\)模擬...於是用\(treap\)寫了個板子. 看上去,我們似乎要維護兩顆樹(寵物和顧客), 然而,註意到,同一時間寵物點只有一類人(或物qwq), 所以,只要判斷當前

P2286寵物收養

get hid amp tchar sub += 別人 節點 tdi 1 #include<cstdio> 2 #define abs(a,b) (a>b?a-b:b-a) 3 #define MOD 1000000 4 #define

P2286寵物收養·改

() mod val right get splay none 空間復雜度 出現 #include<cstdio> #define abs(a,b) (a>b?a-b:b-a) #define MOD 1000000 #define MXN 80000

BZOJ 1208: [HNOI2004]寵物收養

char 分享 整數 到來 content hide des problem pan Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 9314 Solved: 3732[Submit][Status][Discuss] D

HNOI2004寵物收養所(splay維護二叉搜索樹模板題)

個數 正整數 noi 模板題 sea () clu search 公式 描述 最近,阿Q開了一間寵物收養所。收養所提供兩種服務:收養被主人遺棄的寵物和讓新的主人領養這些寵物。每個領養者都希望領養到自己滿意的寵物,阿Q根據領養者的要求通過他自己發明的一個特殊的公式,得出該領

bzoj1208: [HNOI2004]寵物收養

hint a+b ota 情況 led 們的 發生 超過 描述 1208: [HNOI2004]寵物收養所 Time Limit: 10 Sec Memory Limit: 162 MB Description 最近,阿Q開了一間寵物收養所。收養所提供兩種服務:收養被

【BZOJ 1208】[HNOI2004]寵物收養

def 不用 multi name pri 等於 題解 ble ret 【鏈接】 我是鏈接,點我呀:) 【題意】 在這裏輸入題意 【題解】 用set搞。 (因為規定了不會有相同特點值的東西。 所以可以不用multiset. 那麽每次用lower_bound找

P2292 [HNOI2004] L語言 解題報告

ack .cn 現在 using 出現 memset 每次 queue word P2292 [HNOI2004] L語言 題目描述 標點符號的出現晚於文字的出現,所以以前的語言都是沒有標點的。現在你要處理的就是一段沒有標點的文章。 一段文章\(T\)是由若幹小寫字母構成。

P1437 [HNOI2004]敲磚塊(dp)

printf tdi 描述 class reg 一行 open using freopen 題目背景 無 題目描述 在一個凹槽中放置了 n 層磚塊、最上面的一層有n 塊磚,從上到下每層依次減少一塊磚。每塊磚 都有一個分值,敲掉這塊磚就能得到相應的分值,如下圖所示。

P2292 [HNOI2004]L語言

http void get ace targe bool name std mes 傳送門 建好trie樹 當$dp[j]==1$當且僅當存在$dp[k]=1$且$T[k+1,j]==word[i]$ 然後亂搞就行了 1 //minamoto 2 #

P2289 [HNOI2004]郵遞員(插頭dp)

[] val struct ont bit eof using hash += 傳送門 太神仙了……講不來講不來->這裏 1 //minamoto 2 #include<iostream> 3 #i