1. 程式人生 > >LG_2286_[HNOI2004]寵物收養場

LG_2286_[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個)

輸出格式

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

樣例

INPUT

5
0 2
0 4
1 3
1 2
1 5

OUTPUT

3
注:abs(3-2) + abs(2-4)=3,
最後一個領養者沒有寵物可以領養。

SOLUTION

STL之set

dalao都是用splay,treap寫的,像我這樣的比較野雞的選手就只能求助於強大的STL了qwq

(不會平衡樹也不會set???可以學嘛!我有一篇關於set的基本用法的部落格歡迎參觀並提出意見qwq)

本題思維難度偏低,只需要按照題意模擬即可。。。

需要注意的是在使用upper_bound()時需要考慮邊界情況。
即查詢後指標停在第一個元素和最後一個元素時最好特判處理。

long long要開,應該也需要自己手寫一個ABS()(好像因為本題的特點值給的極大。。

而且注意的是,一定要判斷所找到的第一個大於所需特徵值num的元素和它的迭代器的前驅所指向的元素與num的差的ABS的大小,題目資料好像比較水,這個沒寫居然有80pts。。。
還有就是判斷大小的時候不要亂取模,不然就是90pts。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <set>
#include <cmath>
using namespace std;
typedef long long LL;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
    return x*f;}
inline LL ABS(LL A,LL B) {if (A<B) return (B-A);else return (A-B);}
const int N=80100;
const int P=1000000;
const int INF=2147483647;
int n;
std::set<int> pet,kpr;
std::set<int>::iterator iter;
int main(){
    int i,j;
    LL ans=0;
    n=read();int PET=0,KPR=0;
//  pet.insert(INF);kpr.insert(INF);
    for (i=1;i<=n;++i){
        int cls=read(),num=read();
        if (cls==0){
            if (!KPR) {pet.insert(num);PET++;}
            else {iter=kpr.upper_bound(num);
                if (iter==kpr.end()) iter--;
                else if (iter!=kpr.begin()){
                    LL CALC=ABS((*iter),num);
                    iter--;LL NOW=ABS((*iter),num);
                    if (CALC<NOW) iter++;
                }
                ans=(ans+ABS((*iter),num)%P)%P;
                kpr.erase(iter);KPR--;}
        }
        else {
            if (!PET) {kpr.insert(num);KPR++;}
            else{iter =pet.upper_bound(num);
                if (iter==pet.end()) iter--;
                else if (iter!=pet.begin()){
                    LL CALC=ABS((*iter),num);
                    iter--;LL NOW=ABS((*iter),num);
                    if (CALC<NOW) iter++;
                }
                ans=(ans+ABS((*iter),num)%P)%P;
                pet.erase(iter);PET--;
            }
        }
    }
    printf("%lld\n",ans);
    return 0;
}