[题解]bzoj1691 Usaco2007Dec 挑剔的美食家

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,为
所有方案中花费最少的。

Solution

没有权限的同学们可以取这里交:洛谷
由于鲜嫩程度只要求大于,而费用还要求最小,所以我们按照鲜嫩程度排序,从大到小扫一遍,同时用平衡树维护价格,这样就可以对于每个奶牛在鲜嫩程度符合要求的草中选出价格最小的。

代码:

#include
#include
#include
using namespace std;

template<typename T>inline void read(T &x){
    T f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(x=0;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    x*=f;
}

#define mp make_pair

const int maxn=100010,inf=0x7fffffff;
typedef long long LL;
typedef pair<int,int> Pair;
struct node{
    int lc,rc,key,data,size;
    node(){lc=rc=key=data=size=0;}
};
struct Treap{
    int root,cnt;
    node T[maxn];
    Treap(){root=cnt=0;}
    void update(int x){
        T[x].size=T[T[x].lc].size+T[T[x].rc].size+1;
    }
    int Merge(int x,int y){
        if(!x||!y)return x+y;
        if(T[x].keyreturn T[x].rc=Merge(T[x].rc,y),update(x),x;
        else return T[y].lc=Merge(x,T[y].lc),update(y),y;
    }
    Pair Split(int x,int n){
        if(!x||!n)return mp(0,x);
        int lson=T[x].lc,rson=T[x].rc;
        if(T[lson].size==n)return T[x].lc=0,update(x),mp(lson,x);
        if(T[lson].size==n-1)return T[x].rc=0,update(x),mp(x,rson);
        if(T[lson].size>n){
            Pair temp=Split(lson,n);
            return T[x].lc=temp.second,update(x),mp(temp.first,x);
        }
        else{
            Pair temp=Split(rson,n-T[lson].size-1);
            return T[x].rc=temp.first,update(x),mp(x,temp.second);
        }
    }
    int Getrank(int val){
        int x=root,rnk=0;
        while(x){
            if(val<=T[x].data)x=T[x].lc;
            else rnk+=T[T[x].lc].size+1,x=T[x].rc;
        }
        return rnk;
    }
    void Insert(int val){
        if(!root){
            T[root=++cnt].data=val;T[cnt].size=1;
            return T[cnt].key=rand(),void();
        }
        Pair temp=Split(root,Getrank(val));
        int x=++cnt;
        T[x].data=val;T[x].size=1;T[x].key=rand();
        root=Merge(Merge(temp.first,x),temp.second);
    }
    void Delete(int val){
        Pair x=Split(root,Getrank(val));
        Pair y=Split(x.second,1);
        root=Merge(x.first,y.second);
    }
    int Suf(int val){
        int x=root,ans=inf;
        while(x){
            if(val>T[x].data)x=T[x].rc;
            else ans=min(ans,T[x].data),x=T[x].lc;
        }
        return ans;
    }
}tree;
int n,m;
LL ans;
Pair grass[maxn],cow[maxn];

int main(){
    srand(214748364);
    read(n);read(m);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&cow[i].second,&cow[i].first);
    for(int i=1;i<=m;i++)
        scanf("%d%d",&grass[i].second,&grass[i].first);
    sort(cow+1,cow+n+1);sort(grass+1,grass+m+1);
    for(int i=n,j=m;i>=1;i--){
        while(grass[j].first>=cow[i].first&&j>=1)
            tree.Insert(grass[j--].second);
        int temp=tree.Suf(cow[i].second);
        if(temp==inf)return puts("-1"),0;
        ans+=temp;tree.Delete(temp);
    }
    printf("%lld\n",ans);
    return 0;
}

你可能感兴趣的:(数据结构,平衡树)