「BZOJ1691」[Usaco2007 Dec] 挑剔的美食家
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,为
所有方案中花费最少的。
题解
妈蛋 rnd[k]=rand();这句写错调了半个晚上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define ll long long using namespace std; int n,m,sz,rt,tmp; ll ans; int v[100001],l[100001],r[100001],rnd[100001],w[100001]; struct data{int a,b;}a[100001],b[100001]; void ini() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d%d",&a[i].a,&a[i].b); for(int i=1;i<=m;i++)scanf("%d%d",&b[i].a,&b[i].b); } bool cmp(data a,data b){return a.b>b.b;} void rturn(int &k) {int t=l[k];l[k]=r[t];r[t]=k;k=t;} void lturn(int &k) {int t=r[k];r[k]=l[t];l[t]=k;k=t;} void insert(int &k,int x) { if(!k){k=++sz;v[k]=x;w[k]=1;rnd[k]=rand();return;} if(x==v[k])w[k]++; else if(x<v[k]){insert(l[k],x);if(rnd[l[k]]<rnd[k])rturn(k);} else {insert(r[k],x);if(rnd[r[k]]<rnd[k])lturn(k);} } void del(int &k,int x) { if(x==v[k]) { if(w[k]>1)w[k]--; else if(l[k]*r[k]==0)k=l[k]+r[k]; else if(rnd[l[k]]<rnd[r[k]]){rturn(k);del(k,x);} else {lturn(k);del(k,x);} } else if(x<v[k])del(l[k],x); else del(r[k],x); } void find(int k,int x) { if(!k)return; if(v[k]>=x){tmp=v[k];find(l[k],x);} else find(r[k],x); } void solve() { sort(a+1,a+n+1,cmp); sort(b+1,b+m+1,cmp); int j=1; for(int i=1;i<=n;i++) { tmp=-1; while(b[j].b>=a[i].b&&j<=m){insert(rt,b[j].a);j++;} find(rt,a[i].a); if(tmp==-1){puts("-1");return;} ans+=tmp;del(rt,tmp); } printf("%lld",ans); } int main() { ini(); solve(); return 0; } |