1691: [Usaco2007 Dec]挑剔的美食家
Time Limit: 5 Sec
Memory Limit: 64 MB
Submit: 670
Solved: 308
[ 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,为
所有方案中花费最少的。
HINT
Source
[ Submit][ Status][ Discuss]
题解:贪心+splay
把奶牛和牧草都按照价格从小到大排序。
如果奶牛的需求价格小于等于当前牧草的价格,那么就把奶牛所需牧草的新鲜度加入splay中,然后把所有满足条件的奶牛的新鲜度加入splay后,在把当前牧草的新鲜度加入splay,然后查找当前牧草的前驱,如果有就把前驱点的个数--,当期牧草的价格计入答案,再删去牧草的新鲜度,如果没有前驱点就直接删去牧草的新鲜度。如果最后splay中节点个数为0,则说明全部奶牛都匹配成功,输出答案,否则输出-1。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 200003
using namespace std;
int n,m;
struct data
{
int c,num;
};data cow[N],grass[N];
int fa[N],ch[N][3],key[N],size[N],cnt[N],tot,root;
long long ans;
int cmp(data a,data b)
{
return a.c<b.c||a.c==b.c&&a.num<b.num;
}
int get(int x)
{
return ch[fa[x]][1]==x;
}
void clear(int x)
{
size[x]=cnt[x]=key[x]=ch[x][1]=ch[x][0]=fa[x]=0;
}
void update(int x)
{
size[x]=cnt[x];
if (ch[x][0]) size[x]+=size[ch[x][0]];
if (ch[x][1]) size[x]+=size[ch[x][1]];
}
void rotate(int x)
{
int y=fa[x]; int z=fa[y]; int which=get(x);
if (z)
ch[z][ch[z][1]==y]=x;
ch[y][which]=ch[x][which^1]; fa[ch[y][which]]=y;
fa[y]=x; fa[x]=z; ch[x][which^1]=y;
update(y); update(x);
}
void splay(int x)
{
for (int f;(f=fa[x]);rotate(x))
if (fa[f])
rotate(get(x)==get(f)?f:x);
root=x;
}
void insert(int x)
{
if (!root)
{
root=++tot;
clear(tot); size[tot]=cnt[tot]=1; key[tot]=x;
return ;
}
int now=root; int f=0;
while (true)
{
if (x==key[now])
{
cnt[now]++;
update(now); update(f); splay(now);
return;
}
f=now;
now=ch[now][key[now]<x];
if (!now)
{
tot++; clear(tot);
cnt[tot]=size[tot]=1; key[tot]=x;
fa[tot]=f; ch[f][key[f]<x]=tot;
update(f); splay(tot); return;
}
}
}
int find(int x)
{
int now=root; int ans=0;
while (true)
{
if (x==key[now])
return now;
if (x<key[now])
now=ch[now][0];
else
now=ch[now][1];
}
}
int pre()
{
if (cnt[root]>1) return root;
int now=ch[root][0];
while (ch[now][1]) now=ch[now][1];
return now;
}
void del(int x)
{
splay(x);
if (cnt[root]>1)
{
cnt[root]--;
update(root); splay(root);
return ;
}
if (!ch[root][0]&&!ch[root][1])
{
clear(root);
root=0;
return;
}
if (!ch[root][1])
{
int old=root; root=ch[root][0]; fa[root]=0; clear(old);
return;
}
if (!ch[root][0])
{
int old=root; root=ch[root][1]; fa[root]=0; clear(old);
return ;
}
int k=pre(); int old=root; splay(k);
ch[k][1]=ch[old][1]; fa[ch[old][1]]=k;
clear(old);
update(k);
return ;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d%d",&cow[i].c,&cow[i].num);
for (int i=1;i<=m;i++)
scanf("%d%d",&grass[i].c,&grass[i].num);
sort(cow+1,cow+n+1,cmp);
sort(grass+1,grass+m+1,cmp);
int j=1;
for (int i=1;i<=m;i++)
{
while (cow[j].c<=grass[i].c&&j<=n)
insert(cow[j].num),j++;
insert(grass[i].num);
int k=pre();
if (k)
{
ans=(long long) ans+grass[i].c;
del(k);
}
k=find(grass[i].num);
del(k);
}
// cout<<ans<<endl;
if (size[root]==0&&j>n)
printf("%lld\n",ans);
else
printf("-1\n");
return 0;
}