1691: [Usaco2007 Dec]挑剔的美食家
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
1 1
2 3
1 4
4 2
3 2
2 1
4 3
5 2
5 4
2 6
4 4
Sample Output
输出说明:
给奶牛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 key[maxn],lc[maxn],rc[maxn],fa[maxn],siz[maxn]; 13 LL tot,root; 14 LL N,M,ANS; 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 update(LL x){ 30 siz[x]=siz[lc[x]]+1+siz[rc[x]]; 31 } 32 void r_rotate(LL x){ 33 LL y=fa[x]; 34 lc[y]=rc[x]; 35 if(rc[x]!=0) fa[rc[x]]=y; 36 fa[x]=fa[y]; 37 if(y==lc[fa[y]]) lc[fa[y]]=x; 38 else rc[fa[y]]=x; 39 fa[y]=x; rc[x]=y; 40 update(x); update(y); 41 } 42 void l_rotate(LL x){ 43 LL y=fa[x]; 44 rc[y]=lc[x]; 45 if(lc[x]!=0) fa[lc[x]]=y; 46 fa[x]=fa[y]; 47 if(y==lc[fa[y]]) lc[fa[y]]=x; 48 else rc[fa[y]]=x; 49 fa[y]=x; lc[x]=y; 50 update(x); update(y); 51 } 52 void splay(LL x,LL s){ 53 LL p; 54 while(fa[x]!=s){ 55 p=fa[x]; 56 if(fa[p]==s){ 57 if(x==lc[p]) r_rotate(x); 58 else l_rotate(x); 59 break; 60 } 61 if(x==lc[p]){ 62 if(p==lc[fa[p]]) r_rotate(p),r_rotate(x); 63 else r_rotate(x),l_rotate(x); 64 } 65 else{ 66 if(p==rc[fa[p]]) l_rotate(p),l_rotate(x); 67 else l_rotate(x),r_rotate(x); 68 } 69 } 70 if(s==0) root=x; 71 update(x); 72 } 73 LL find(LL v){//查找在这棵树中键值为v的节点 74 LL x=root; 75 while(x!=0){ 76 if(v<key[x]) x=lc[x]; 77 else if(v>key[x]) x=rc[x]; 78 else if(v==key[x]){ 79 splay(x,0); 80 return x; 81 } 82 } 83 return -1; 84 } 85 void New_node(LL &x,LL fath,LL v){//建立新节点 86 x=++tot; 87 lc[x]=rc[x]=0; siz[x]=1; 88 fa[x]=fath; 89 key[x]=v; 90 } 91 void insert(LL v){//插入新节点 92 if(root==0){ 93 New_node(rc[0],0,v); 94 root=tot; 95 return ; 96 } 97 LL p,x=root; 98 while(x!=0){ 99 p=x; 100 if(v<=key[x]) siz[x]++,x=lc[x]; 101 else siz[x]++,x=rc[x]; 102 } 103 if(v<=key[p]) New_node(lc[p],p,v); 104 else New_node(rc[p],p,v); 105 splay(tot,0); 106 } 107 LL getmax(LL x){//找到以x为根的最大值 108 if(rc[x]!=0) return getmax(rc[x]); 109 return x; 110 } 111 LL getmin(LL x){//找到以x为根的最小值 112 if(lc[x]!=0) return getmin(lc[x]); 113 return x; 114 } 115 void Delete(LL v){ 116 LL x=find(v); 117 LL pp=getmax(lc[x]); 118 LL nn=getmin(rc[x]); 119 if(lc[x]==0||rc[x]==0){ 120 if(lc[x]==0&&rc[x]==0){ 121 root=0; rc[0]=0; 122 return ; 123 } 124 if(lc[x]==0){ 125 rc[0]=rc[x]; fa[rc[x]]=0; root=rc[x]; rc[x]=0; 126 siz[x]=1; 127 return ; 128 } 129 else{ 130 rc[0]=lc[x]; fa[lc[x]]=0; root=lc[x]; lc[x]=0; 131 siz[x]=1; 132 return ; 133 } 134 } 135 splay(pp,0); 136 splay(nn,root); 137 fa[lc[nn]]=0; siz[lc[nn]]=1; lc[nn]=0; 138 update(nn); update(pp); 139 } 140 LL succ(LL rt,LL v){//返回比 v大的最小的数 141 if(rt==0) return v; 142 if(v>=key[rt]) return succ(rc[rt],v); 143 else{ 144 LL ans=succ(lc[rt],v); 145 if(ans==v) return key[rt]; 146 return ans; 147 } 148 } 149 int main(){ 150 scanf("%lld%lld",&N,&M); 151 if(M<N){ 152 printf("-1"); 153 return 0; 154 } 155 for(LL i=1;i<=N;i++) scanf("%lld%lld",&cow[i].a,&cow[i].b); 156 for(LL i=1;i<=M;i++) scanf("%lld%lld",&gra[i].a,&gra[i].b); 157 sort(cow+1,cow+N+1,cmp); sort(gra+1,gra+M+1,cmp2); 158 for(LL i=1,j=1;i<=N;i++){ 159 while(gra[j].b>=cow[i].b&&j<=M) 160 insert(gra[j++].a); 161 if(siz[root]==0){printf("-1"); return 0;} 162 if(find(cow[i].a)!=-1){ 163 ANS+=cow[i].a; 164 Delete(cow[i].a); 165 } 166 else{ 167 LL num=succ(root,cow[i].a); 168 ANS+=num; 169 Delete(num); 170 } 171 } 172 printf("%lld",ANS); 173 return 0; 174 }
以上是关于1691: [Usaco2007 Dec]挑剔的美食家的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 1691: [Usaco2007 Dec]挑剔的美食家 [treap 贪心]
bzoj1691[Usaco2007 Dec]挑剔的美食家*
BZOJ_1691_[Usaco2007 Dec]挑剔的美食家_贪心