1691: [Usaco2007 Dec]挑剔的美食家

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1691: [Usaco2007 Dec]挑剔的美食家相关的知识,希望对你有一定的参考价值。

Time Limit: 5 Sec  Memory Limit: 64 MB
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

Sample Output

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 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]挑剔的美食家的主要内容,如果未能解决你的问题,请参考以下文章

1691: [Usaco2007 Dec]挑剔的美食家

BZOJ 1691: [Usaco2007 Dec]挑剔的美食家 [treap 贪心]

bzoj1691[Usaco2007 Dec]挑剔的美食家*

BZOJ_1691_[Usaco2007 Dec]挑剔的美食家_贪心

贪心+TreapBZOJ1691-[Usaco2007 Dec]挑剔的美食家

BZOJ 1691 usaco2007 挑剔的美食家