1691: [Usaco2007 Dec]挑剔的美食家
Time Limit: 5 Sec
Memory Limit: 64 MB
Submit: 595
Solved: 263
[ 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,为
所有方案中花费最少的。
平衡树+贪心。。bzoj里面不能用srand(time(0)).........
首先将所有数据按钱为第一关键字新鲜度为第二关键字排序
从小到大枚举牧草,把符合钱的牛扔进平衡树,显然我们需要找到平衡树内满足条件且第二关键字最大的
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<cstdlib>
#include<map>
#include<cmath>
#include<ctime>
using namespace std;
const int maxn = 1e5 + 10;
struct G{
int p,v;
bool operator < (const G &b) const{
if (p < b.p) return 1;
if (p > b.p) return 0;
return v < b.v;
}
}cow[maxn],gra[maxn];
class data{
private:
struct Node{
int pri,val;
Node *ch[2];
}*root,*tot,pool[maxn];
void rotate(Node *&x,int d)
{
Node *y = x->ch[d];
x->ch[d] = y->ch[d^1];
y->ch[d^1] = x;
x = y;
}
void Insert(Node *&x,int pri,int val)
{
if (x == NULL)
{
x = tot++;
x->pri = pri; x->val = val;
x->ch[0] = NULL; x->ch[1] = NULL;
return;
}
int d = x->val > val ? 0:1;
Insert(x->ch[d],pri,val);
if (x->ch[d]->pri > x->pri) rotate(x,d);
}
void Remove(Node *&x,int val)
{
int d = x->val > val ? 0:1;
if (x->val == val)
{
if (x->ch[0] == NULL && x->ch[1] == NULL)
{
x = NULL;
return;
}
if (x->ch[0] == NULL && x->ch[1] != NULL)
{
x = x->ch[1];
return;
}
if (x->ch[1] == NULL && x->ch[0] != NULL)
{
x = x->ch[0];
return;
}
int d1 = x->ch[0]->pri > x->ch[1]->pri?0:1;
rotate(x,d1);
Remove(x->ch[d1^1],val);
return;
}
Remove(x->ch[d],val);
}
int Lower_bound(Node *x,int val)
{
int ret = -1;
while (x != NULL)
{
int d = x->val > val ? 0:1;
if (x->val <= val) ret = max(ret,x->val);
x = x->ch[d];
}
return ret;
}
public:
data(){root = NULL; tot = pool;}
void Ins(int val){Insert(root,rand(),val);}
void Rem(int val){Remove(root,val);}
int L_b(int val){return Lower_bound(root,val);}
};
int n,m,i,j;
long long ans = 0;
int main()
{
#ifndef ONLINE_JUDGE
#ifndef YZY
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#else
freopen("yzy.txt","r",stdin);
#endif
#endif
//srand(time(0));
static data tree;
//tree.Ins(2E9);
cin >> n >> m;
for (i = 1; i <= n; i++) scanf("%d%d",&cow[i].p,&cow[i].v);
for (i = 1; i <= m; i++) scanf("%d%d",&gra[i].p,&gra[i].v);
sort (cow + 1,cow + n + 1);
sort (gra + 1,gra + m + 1);
j = 1; int sat = 0;
for (i = 1; i <= m; i++)
{
while (j <= n && cow[j].p <= gra[i].p)
tree.Ins(cow[j++].v);
int val = tree.L_b(gra[i].v);
if (val != -1)
{
ans += 1LL*gra[i].p;
tree.Rem(val);
++sat;
if (sat == n)
{
cout << ans;
return 0;
}
}
}
cout << -1;
return 0;
}