bzoj 1691: [Usaco2007 Dec]挑剔的美食家
Submit: 621 Solved: 280
[Submit][Status][Discuss]
Description
与很多奶牛一样,Farmer John那群养尊处优的奶牛们对食物越来越挑剔,随便拿堆草就能打发她们午饭的日子自然是一去不返了。现在,Farmer John不得不去牧草专供商那里购买大量美味多汁的牧草,来满足他那N(1 <= N <= 100,000)头挑剔的奶牛。 所有奶牛都对FJ提出了她对牧草的要求:第i头奶牛要求她的食物每份的价钱不低于A_i(1 <= A_i <= 1,000,000,000),并且鲜嫩程度不能低于B_i(1 <= B_i <= 1,000,000,000)。商店里供应M(1 <= M <= 100,000)种不同的牧草,第i 种牧草的定价为C_i(1 <= C_i <= 1,000,000,000),鲜嫩程度为D_i (1 <= D_i <= 1,000,000,000)。 为了显示她们的与众不同,每头奶牛都要求她的食物是独一无二的,也就是说,没有哪两头奶牛会选择同一种食物。 Farmer John想知道,为了让所有奶牛满意,他最少得在购买食物上花多少钱。
Input
* 第1行: 2个用空格隔开的整数:N 和 M
* 第2..N+1行: 第i+1行包含2个用空格隔开的整数:A_i、B_i * 第N+2..N+M+1行: 第j+N+1行包含2个用空格隔开的整数:C_i、D_i
Output
* 第1行: 输出1个整数,表示使所有奶牛满意的最小花费。如果无论如何都无法 满足所有奶牛的需求,输出-1
Sample Input
4 7
1 1
2 3
1 4
4 2
3 2
2 1
4 3
5 2
5 4
2 6
4 4
1 1
2 3
1 4
4 2
3 2
2 1
4 3
5 2
5 4
2 6
4 4
Sample Output
12
输出说明:
给奶牛1吃价钱为2的2号牧草,奶牛2吃价钱为4的3号牧草,奶牛3分到价钱
为2的6号牧草,奶牛4选择价钱为4的7号牧草,这种分配方案的总花费是12,为
所有方案中花费最少的。
输出说明:
给奶牛1吃价钱为2的2号牧草,奶牛2吃价钱为4的3号牧草,奶牛3分到价钱
为2的6号牧草,奶牛4选择价钱为4的7号牧草,这种分配方案的总花费是12,为
所有方案中花费最少的。
Source Gold
题解:
让牛和草按照鲜嫩度排序,然后对于第i头奶牛,把所有新鲜度大于它要求的价值塞到一个平衡树里,每次ANS加上当前平衡树中它要求的价值的后继,但一定要先判断一下有没有和它要求的价值正好相等的草。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cmath> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 using namespace std; 10 typedef long long LL; 11 const LL maxn=200010; 12 LL root,tot,N,M; 13 LL ANS; 14 LL key[maxn],siz[maxn],lc[maxn],rc[maxn]; 15 struct COW{ 16 LL a,b; 17 }cow[maxn]; 18 struct G{ 19 LL a,b; 20 }gra[maxn]; 21 bool cmp(const COW&w,const COW &e){ 22 if(w.b>e.b) return 1; 23 return 0; 24 } 25 bool cmp2(const G&w,const G &e){ 26 if(w.b>e.b) return 1; 27 return 0; 28 } 29 void r_rotate(LL &rt){ 30 LL k=lc[rt]; 31 lc[rt]=rc[k]; 32 rc[k]=rt; 33 siz[k]=siz[rt]; 34 siz[rt]=siz[lc[rt]]+siz[rc[rt]]+1; 35 rt=k; 36 } 37 void l_rotate(LL &rt){ 38 LL k=rc[rt]; 39 rc[rt]=lc[k]; 40 lc[k]=rt; 41 siz[k]=siz[rt]; 42 siz[rt]=siz[lc[rt]]+siz[rc[rt]]+1; 43 rt=k; 44 } 45 void MAINTAIN(LL &rt,bool flag){ 46 if(flag==false){ 47 if(siz[lc[lc[rt]]]>siz[rc[rt]]) r_rotate(rt); 48 else if(siz[rc[lc[rt]]]>siz[rc[rt]]){ 49 l_rotate(lc[rt]); 50 r_rotate(rt); 51 } 52 else return; 53 } 54 else{ 55 if(siz[rc[rc[rt]]]>siz[lc[rt]]) l_rotate(rt); 56 else if(siz[lc[rc[rt]]]>siz[lc[rt]]){ 57 r_rotate(rc[rt]); 58 l_rotate(rt); 59 } 60 else return; 61 } 62 MAINTAIN(lc[rt],0); MAINTAIN(rc[rt],1); 63 MAINTAIN(rt,1); MAINTAIN(rt,0); 64 } 65 void insert(LL &rt,LL v){ 66 if(rt==0){ 67 rt=++tot; 68 key[rt]=v; 69 lc[rt]=rc[rt]=0; siz[rt]=1; 70 return ; 71 } 72 siz[rt]++; 73 if(v<=key[rt]) insert(lc[rt],v); 74 else insert(rc[rt],v); 75 MAINTAIN(rt,v>key[rt]); 76 } 77 LL Delete(LL &rt,LL v){ 78 LL ans; 79 siz[rt]--; 80 if(v==key[rt]||(v<key[rt]&&lc[rt]==0)||(v>key[rt]&&rc[rt]==0)){ 81 ans=key[rt]; 82 if(lc[rt]==0||rc[rt]==0) rt=lc[rt]+rc[rt]; 83 else key[rt]=Delete(lc[rt],key[rt]+1); 84 return ans; 85 } 86 if(v<key[rt]) ans=Delete(lc[rt],v); 87 else ans=Delete(rc[rt],v); 88 return ans; 89 } 90 LL succ(LL &rt,LL v){//返回比v大的最小的数 91 if(rt==0) return v; 92 if(v>=key[rt]) return succ(rc[rt],v); 93 else{ 94 LL ans=succ(lc[rt],v); 95 if(ans==v) return key[rt]; 96 return ans; 97 } 98 } 99 bool find(LL &rt,LL v){//查找是否有 key值为 v的节点 100 if(rt==0) return false; 101 else if(v==key[rt]) return true; 102 else if(v<key[rt]) return find(lc[rt],v); 103 else if(v>key[rt]) return find(rc[rt],v); 104 } 105 106 int main(){ 107 scanf("%lld%lld",&N,&M); 108 if(M<N){ 109 printf("-1"); 110 return 0; 111 } 112 for(LL i=1;i<=N;i++) scanf("%lld%lld",&cow[i].a,&cow[i].b); 113 for(LL i=1;i<=M;i++) scanf("%lld%lld",&gra[i].a,&gra[i].b); 114 sort(cow+1,cow+N+1,cmp); sort(gra+1,gra+M+1,cmp2); 115 for(LL i=1,j=1;i<=N;i++){ 116 while(gra[j].b>=cow[i].b&&j<=M) 117 insert(root,gra[j++].a); 118 if(siz[root]==0){printf("-1"); return 0;} 119 if(find(root,cow[i].a)==true){ 120 ANS+=cow[i].a; 121 Delete(root,cow[i].a); 122 } 123 else{ 124 LL num=succ(root,cow[i].a); 125 ANS+=num; 126 Delete(root,num); 127 } 128 } 129 printf("%lld",ANS); 130 return 0; 131 }