【平衡树】挑剔的美食家

问题描述

与很多奶牛一样,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想知道,为了让所有奶牛满意,他最少得在购买食物上花多少钱。

输入格式

第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

输出格式

输出1个整数,表示使所有奶牛满意的最小花费。如果无论如何都无法满足所有奶牛的需求,输出-1

样例输入 1

4 7
1 1
2 3
1 4
4 2
3 2
2 1
4 3
5 2
5 4
2 6
4 4

样例输出 1

12

样例输入 2

10 30
750 639
744 277
156 601
93 165
460 303
664 433
433 430
163 267
844 152
564 603
556 346
423 800
1042 1080
924 254
1001 983
373 852
1019 774
862 113
356 216
1319 185
141 177
674 48
939 202
219 1415
981 801
157 717
959 101
985 453
593 958
579 354
166 396
915 477
1214 1340
102 847
134 568
753 1008
984 665
867 907
1000 644
771 887

样例输出 2

5804

样例1说明

给奶牛1吃价钱为2的2号牧草,奶牛2吃价钱为4的3号牧草,奶牛3分到价钱为2的6号牧草,奶牛4选择价钱为4的7号牧草,这种分配方案的总花费是12,为所有方案中花费最少的。


题解

我们先把奶牛的要求按鲜嫩度排序,把牧草也按鲜嫩度排序。每讨论到一个奶牛,就把所有鲜嫩度不低于要求的牧草加进一棵平衡树中按价格排好,再取出该点(奶牛)的后继加进答案中。如果没有后继,则输出-1 。


代码

#include <cstdio>
#include <algorithm>
#include <iostream>
#define ll long long
using namespace std;
const ll Q=200005;
ll ls[Q],rs[Q],v[Q],f[Q],tot=0,n,root=0,temp[Q];
struct dt{
    ll gr,co;
}a[Q],b[Q];
bool cmp(dt a,dt b)
{return a.gr>b.gr;}
void lx(ll x)
{
    ll y=f[x],z=f[y];
    if(z)if(ls[z]==y)ls[z]=x;
    else rs[z]=x;
    f[x]=z;
    rs[y]=ls[x];
    f[rs[y]]=y;
    f[y]=x;
    ls[x]=y;
}
void rx(ll x)
{
    ll y=f[x],z=f[y];
    if(z)if(ls[z]==y)ls[z]=x;
    else rs[z]=x;
    f[x]=z;
    ls[y]=rs[x];
    f[ls[y]]=y;
    f[y]=x;
    rs[x]=y;
}
void splay(ll x)
{
    while(f[x])
    {
        ll y=f[x],z=f[y];
        if(z)
            if(ls[z]==y)
                if(ls[y]==x)rx(y),rx(x);
                else lx(x),rx(x);
            else if(rs[y]==x)lx(y),lx(x);
                else rx(x),lx(x);
        else
            if(ls[y]==x)rx(x);
            else lx(x);
    }
    root=x;
}
ll ins(ll x)
{
    if(!root){
        v[++tot]=x;temp[tot]=1;
        root=tot;
        f[tot]=0;
        return tot;
    }
    ll p=root;
    while(p){
        if(x==v[p]){++temp[p];splay(p);return p;}
        if(x<v[p])
            if(ls[p])p=ls[p];
            else {ls[p]=++tot;break;}
        else if(rs[p])p=rs[p];
            else {rs[p]=++tot;break;}
    }
    v[tot]=x;
    f[tot]=p;
    temp[tot]=1;
    splay(tot);
    return tot;
}
ll gm(ll p)
{
    if(!p)return -1;
    while(rs[p])p=rs[p];
    return p;
}
ll gs(ll p)
{
    if(!p)return -1;
    while(ls[p])p=ls[p];
    return p;
}
void del(ll x)
{
    splay(x);
    temp[x]--;
    if(temp[x]>0)return;
    ll lls=ls[x],rrs=rs[x];
    f[lls]=f[rrs]=ls[x]=rs[x]=0;
    if(!lls){root=rrs;return;}
    root=lls;
    lls=gm(lls);
    splay(lls);
    rs[lls]=rrs;
    f[rrs]=lls;
}
int main()
{
    ll i,n,m,t=1,ans=0;
    scanf("%lld%lld",&n,&m);
    for(i=1;i<=n;i++)
        scanf("%lld%lld",&a[i].co,&a[i].gr);
    for(i=1;i<=m;i++)
        scanf("%lld%lld",&b[i].co,&b[i].gr);
    sort(a+1,a+n+1,cmp),sort(b+1,b+m+1,cmp);
    for(i=1;i<=n;i++)
    {
        while(t<=m&&b[t].gr>=a[i].gr)ins(b[t].co),++t;
        if(root==0){printf("-1");return 0;}
        ll ha=ins(a[i].co-1);
        if(rs[ha]){
            ll temp=gs(rs[ha]);
            ans+=v[temp];
            del(ha),del(temp);
        }
        else{printf("-1",i,a[i].gr,a[i].co,ha);return 0;}
    }
    printf("%lld",ans);
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
malloc lab平衡树是一个在C语言中实现的数据结构,其目的是通过动态内存分配函数malloc来构建一个平衡二叉树。 平衡树,是指左右子树的高度差最多为1的二叉排序树。为了保持树的平衡,我们需要在插入和删除节点时进行相应的旋转操作。由于malloc函数的特性是分配一块连续的内存块,我们可以利用这一特性来构建平衡树。 首先,我们需要定义一个节点结构体,其中包含左右子节点指针、键值和平衡因子等信息。然后,我们通过malloc函数动态分配一个节点并初始化,将其插入到平衡树中。 在插入节点时,我们需要根据节点的键值和当前根节点的键值比较来确定插入的位置。如果键值小于当前节点的键值,则将其插入到当前节点的左子树中;如果键值大于当前节点的键值,则将其插入到当前节点的右子树中。然后,我们需要更新插入路径上各个节点的平衡因子,并进行相应的旋转操作来调整树的平衡性。 在删除节点时,我们也需要进行相应的旋转操作来保持树的平衡性。首先,我们需要找到要删除的节点,并进行删除操作。然后,我们需要根据删除路径上各个节点的平衡因子来进行旋转操作。 通过动态内存分配函数malloc,我们可以灵活地构建和调整平衡树。但需要注意的是,使用malloc函数分配的内存需要在使用后进行释放,以避免内存泄漏问题。因此,在删除节点后,我们需要使用free函数释放相应的内存空间。 总而言之,malloc lab平衡树是一种利用动态内存分配函数malloc来构建的平衡二叉树,通过插入和删除节点,并进行相应的旋转操作来保持树的平衡性。这是一种高效的数据结构,可以在C语言中灵活地使用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值