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以後的結果。

點選檢視程式碼
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int N = 1e5;
const int mod = 1e6;
int n, ans;
int type;
const int MAX_LEVEL = 30;
struct node
{
    int key;
    int next[MAX_LEVEL + 5];
} sl[N + 10];
int node_tot, head, tail, size;
int st[N + 10], top;
int rand_level()
{
    int ret = 1;
    while (rand() % 2 && ret < MAX_LEVEL)
    {
        ++ret;
    }
    return ret;
}
void new_node(int &p, int key = 0)
{
    if (top)
    {
        p = st[top--];
    }
    else
    {
        p = ++node_tot;
    }
    sl[p].key = key;
    ++size;
}
void free_node(int p)
{
    st[++top] = p;
    --size;
}
void init()
{
    new_node(head, -0x3f3f3f3f), new_node(tail, 0x3f3f3f3f);
    for (int i = 1; i <= MAX_LEVEL; ++i)
    {
        sl[head].next[i] = tail;
    }
}
void insert(int key)
{
    int p = head;
    int update[MAX_LEVEL + 5];
    int k = rand_level();
    for (int i = MAX_LEVEL; i; --i)
    {
        while (sl[p].next[i] ^ tail && sl[sl[p].next[i]].key < key)
        {
            p = sl[p].next[i];
        }
        update[i] = p;
    }
    int temp;
    new_node(temp, key);
    for (int i = k; i; --i)
    {
        sl[temp].next[i] = sl[update[i]].next[i];
        sl[update[i]].next[i] = temp;
    }
}
void erase(int key)
{
    int p = head;
    int update[MAX_LEVEL + 5];
    for (int i = MAX_LEVEL; i; --i)
    {
        while (sl[p].next[i] ^ tail && sl[sl[p].next[i]].key < key)
        {
            p = sl[p].next[i];
        }
        update[i] = p;
    }
    free_node(sl[p].next[1]);
    for (int i = MAX_LEVEL; i; --i)
    {
        if (sl[sl[update[i]].next[i]].key == key)
        {
            sl[update[i]].next[i] = sl[sl[update[i]].next[i]].next[i];
        }
    }
}
int lb(int key)
{
    int p = head;
    for (int i = MAX_LEVEL; i; --i)
    {
        while (sl[p].next[i] ^ tail && sl[sl[p].next[i]].key < key)
        {
            p = sl[p].next[i];
        }
    }
    return p; // lower_bound 結果 --
}
void answer(int x)
{
    int l = lb(x);
    int r = sl[l].next[1]; //迭代器 ++
    if (sl[l].key ^ -0x3f3f3f3f && x - sl[l].key <= sl[r].key - x)
    {
        ans = (ans + x - sl[l].key) % mod;
        erase(sl[l].key);
    }
    else
    {
        ans = (ans + sl[r].key - x) % mod;
        erase(sl[r].key);
    }
}
int main()
{
    srand(19260817);
    init();
    int x, y;
    scanf("%d", &n);
    while (n--)
    {
        scanf("%d%d", &x, &y);
        if (size == 2)
        {
            type = x, insert(y);
        }
        else if (x == type)
        {
            insert(y);
        }
        else
        {
            answer(y);
        }
    }
    printf("%d\n", ans);
}