bzoj1208 [HNOI2004]宠物收养所(STL,Treap)
1208: [HNOI2004]宠物收养所
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 5956 Solved: 2317
[Submit][Status][Discuss]
Description
最 近,阿Q开了一间宠物收养所。收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物。每个领养者都希望领养到自己满意的宠物,阿Q根据领养 者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领养的宠物的特点值a(a是一个正整数,a<2^31),而他也给每个处在收养所的宠物 一个特点值。这样他就能够很方便的处理整个领养宠物的过程了,宠物收养所总是会有两种情况发生:被遗弃的宠物过多或者是想要收养宠物的人太多,而宠物太 少。 1. 被遗弃的宠物过多时,假若到来一个领养者,这个领养者希望领养的宠物的特点值为a,那么它将会领养一只目前未被领养的宠物中特点值最接近a的一只宠物。 (任何两只宠物的特点值都不可能是相同的,任何两个领养者的希望领养宠物的特点值也不可能是一样的)如果有两只满足要求的宠物,即存在两只宠物他们的特点 值分别为a-b和a+b,那么领养者将会领养特点值为a-b的那只宠物。 2. 收养宠物的人过多,假若到来一只被收养的宠物,那么哪个领养者能够领养它呢?能够领养它的领养者,是那个希望被领养宠物的特点值最接近该宠物特点值的领养 者,如果该宠物的特点值为a,存在两个领养者他们希望领养宠物的特点值分别为a-b和a+b,那么特点值为a-b的那个领养者将成功领养该宠物。 一个领养者领养了一个特点值为a的宠物,而它本身希望领养的宠物的特点值为b,那么这个领养者的不满意程度为abs(a-b)。
【任务描述】你得到了一年 当中,领养者和被收养宠物到来收养所的情况,希望你计算所有收养了宠物的领养者的不满意程度的总和。这一年初始时,收养所里面既没有宠物,也没有领养者。
Input
第 一行为一个正整数n,n<=80000,表示一年当中来到收养所的宠物和领养者的总数。接下来的n行,按到来时间的先后顺序描述了一年当中来到收养 所的宠物和领养者的情况。每行有两个正整数a, b,其中a=0表示宠物,a=1表示领养者,b表示宠物的特点值或是领养者希望领养宠物的特点值。(同一时间呆在收养所中的,要么全是宠物,要么全是领养 者,这些宠物和领养者的个数不会超过10000个)
Output
仅有一个正整数,表示一年当中所有收养了宠物的领养者的不满意程度的总和mod 1000000以后的结果。
Sample Input
0 2
0 4
1 3
1 2
1 5
Sample Output
(abs(3-2) + abs(2-4)=3,最后一个领养者没有宠物可以领养)
HINT
【思路】
构造一个集合,提供插入/删除/查找(小/大)的操作。
据题意,当宠物或收养者不够用的时候将两者转换一下角色。
这个集合可以用STL中的set或自写Treap实现。
【代码1】
1 #include<set> 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 7 const int INF = 1e9; 8 const int MOD = 1000000; 9 10 set<int> s; 11 set<int> ::iterator it; 12 int n,a,b,c,ans; 13 14 int main() { 15 scanf("%d",&n); 16 s.insert(INF),s.insert(-INF); 17 while(n--) { 18 scanf("%d%d",&a,&b); 19 if(s.size()==2) s.insert(b),c=a; //不够用的情况下交换宠物与收养者的角色 20 else if(a==c) s.insert(b); 21 else { 22 it=s.lower_bound(b); 23 int r=*it-b; 24 int l=b-*(--it); 25 if(l<=r) ans+=l,s.erase(it); 26 else 27 ans+=r,s.erase(++it); 28 ans%=MOD; 29 } 30 } 31 printf("%d\n",ans); 32 return 0; 33 }
【代码2】
1 #include<cstdio> 2 #include<ctime> 3 #include<cstring> 4 #include<cstdlib> 5 #include<iostream> 6 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 7 using namespace std; 8 9 const int MOD = 1000000; 10 struct Node{ 11 Node* ch[2]; 12 int v,r; 13 Node(int w) :v(w) { ch[0]=ch[1]=NULL; r=rand(); } 14 int cmp(int x) const { 15 if(x==v) return -1; return x<v? 0:1; 16 } 17 }; 18 Node* root; 19 20 void rotate(Node* &o,int d) { 21 Node*k=o->ch[d^1]; o->ch[d^1]=k->ch[d]; k->ch[d]=o; o=k; 22 } 23 void insert(Node* &o,int x) { 24 if(o==NULL) o=new Node(x); 25 else { 26 int d=o->cmp(x); if(d==-1) return ; 27 insert(o->ch[d],x); 28 if(o->ch[d]->r > o->r) rotate(o,d^1); 29 } 30 } 31 void remove(Node* &o,int x) { 32 if(o==NULL) return ; 33 int d=o->cmp(x); 34 if(d==-1) { 35 Node* u=o; 36 if(o->ch[0]!=NULL && o->ch[1]!=NULL) { 37 int d2=o->ch[0]->r > o->ch[1]->r? 1:0; 38 rotate(o,d2); remove(o->ch[d2],x); 39 } 40 else { 41 if(o->ch[0]!=NULL) o=o->ch[0]; else o=o->ch[1]; 42 delete u; 43 } 44 } 45 else remove(o->ch[d],x); 46 } 47 void query1(Node* o,int x,int& ans) { 48 if(o==NULL) return ; 49 if(o->v <= x) { ans=o->v; query1(o->ch[1],x,ans); } 50 else query1(o->ch[0],x,ans); 51 } 52 void query2(Node* o,int x,int& ans) { 53 if(o==NULL) return ; 54 if(o->v >= x) { ans=o->v; query2(o->ch[0],x,ans); } 55 else query2(o->ch[1],x,ans); 56 } 57 int n; 58 int abs(int x) { return x<0? -x:x; } 59 60 int main() { 61 int a,b,c,ans=0,ta,tb; 62 scanf("%d",&n); 63 for(int i=0;i<n;i++) { 64 scanf("%d%d",&a,&b); 65 if(root==NULL) root=new Node(b),c=a; 66 else if(c==a) insert(root,b); 67 else { 68 ta=tb=-1; 69 query1(root,b,ta),query2(root,b,tb); 70 if(ta==-1) { ans+=abs(tb-b); remove(root,tb); } 71 else if(tb==-1) { ans+=abs(ta-b); remove(root,ta); } 72 else { 73 if(abs(ta-b)>abs(tb-b)) { ans+=abs(tb-b); remove(root,tb); } 74 else { ans+=abs(ta-b); remove(root,ta); } 75 } 76 ans%=MOD; 77 } 78 } 79 printf("%d\n",ans); 80 return 0; 81 }
posted on 2015-12-10 14:51 hahalidaxin 阅读(251) 评论(0) 编辑 收藏 举报