BZOJ 1208: [HNOI2004]宠物收养所 (Treap)

来源:互联网 发布:全球网络连接图片 编辑:程序博客网 时间:2024/04/29 03:35

BZOJ 1208: [HNOI2004]宠物收养所

题目概述:

有一家宠物收养所,提供两种服务:收养主人遗弃的宠物和让新主人领养宠物.
宠物收养所中总是会有两种情况发生:遗弃宠物过多和领养宠物人过多.
1.遗弃宠物多时,若来一个领养人,领养最接近要求的宠物,若有多只,优先选择小的.
2.领养人多时,若来一只宠物,领养要求最接近的领养,若有多人,优先选择小的.
求领养的宠物的人的不满意度之和,不满意度为领养要求和宠物特点值的差值绝对值.

题目分析:

(又是一道Treap练手题,能一次AC,开心)

结点要么是宠物,要么是人,且在同一时刻仅有一种结点.
所以可以用一个变量state记录Treap当前结点种类.
相同,则插入;不同,则先找前驱或者后继,再删除结点.
需要注意结点为空时,选择插入结点.

代码:

#include<cstdio>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const int MOD=1000000;const ll INF=(1ll<<60);const int maxn=80000+10;#define lc ch[u][0]#define rc ch[u][1]ll key[maxn];int state,root,id;//state判断结点种类int ch[maxn][2],rnd[maxn];void rotate(int& u,int d){    int v=ch[u][d^1];    ch[u][d^1]=ch[v][d];    ch[v][d]=u;u=v;}void insert(int& u,int val){    if(!u) {        u=++id;        rc=lc=0;        key[u]=val;        rnd[u]=rand();        return ;    }    int d=val>key[u];    insert(ch[u][d],val);    if(rnd[u]>rnd[ch[u][d]]) rotate(u,d^1);}bool remove(int& u,int val){    if(!u) return false;    if(val==key[u]) {        if(!lc||!rc) return u=lc?lc:rc,true;        if(rnd[lc]>rnd[rc]) rotate(u,0);        else rotate(u,1);        return remove(u,val);    }    int d=val>key[u];    return remove(ch[u][d],val);}ll find_pre(int val){    int u=root;    ll pre=-INF;    while(u) {        if(val>key[u]) pre=key[u],u=rc;        else u=lc;    }    return pre;}ll find_nxt(int val){    int u=root;    ll nxt=INF;    while(u) {        if(val<key[u]) nxt=key[u],u=lc;        else u=rc;    }    return nxt;}int query(int val){    ll pre=find_pre(val);    ll nxt=find_nxt(val);    if(nxt-val<val-pre) return remove(root,nxt),(nxt-val)%MOD;    else return remove(root,pre),(val-pre)%MOD;}int main(){    int n,a,b,ans=0;    scanf("%d",&n);    while(n--) {        scanf("%d%d",&a,&b);        if(!root||a==state) insert(root,b),state=a;        else (ans+=query(b))%=MOD;    }    printf("%d\n",ans);    return 0;}
0 0
原创粉丝点击