zoukankan      html  css  js  c++  java
  • 1691: [Usaco2007 Dec]挑剔的美食家

    Time Limit: 5 Sec  Memory Limit: 64 MB
    Submit: 621  Solved: 280
    [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,为
    所有方案中花费最少的。

    Source Gold

    题解

      让牛和草按照鲜嫩度排序,然后对于第i头奶牛,把所有新鲜度大于它要求的价值塞到一个伸展树里,每次ANS加上当前伸展树中它要求的价值的后继,但一定要先判断一下有没有和它要求的价值正好相等的草。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<cmath>
      6 #include<algorithm>
      7 #include<vector>
      8 #include<queue>
      9 using namespace std;
     10 typedef long long LL;
     11 const LL maxn=200010;
     12 LL key[maxn],lc[maxn],rc[maxn],fa[maxn],siz[maxn];
     13 LL tot,root;
     14 LL N,M,ANS;
     15 struct COW{
     16     LL a,b;
     17 }cow[maxn];
     18 struct G{
     19     LL a,b;
     20 }gra[maxn];
     21 bool cmp(const COW&w,const COW &e){
     22     if(w.b>e.b) return 1;
     23     return 0;
     24 }
     25 bool cmp2(const G&w,const G &e){
     26     if(w.b>e.b) return 1;
     27     return 0;
     28 }
     29 void update(LL x){
     30     siz[x]=siz[lc[x]]+1+siz[rc[x]];
     31 }
     32 void r_rotate(LL x){
     33     LL y=fa[x];
     34     lc[y]=rc[x]; 
     35     if(rc[x]!=0) fa[rc[x]]=y; 
     36     fa[x]=fa[y];
     37     if(y==lc[fa[y]]) lc[fa[y]]=x;
     38     else rc[fa[y]]=x;
     39     fa[y]=x; rc[x]=y;
     40     update(x); update(y);
     41 }
     42 void l_rotate(LL x){
     43     LL y=fa[x];
     44     rc[y]=lc[x];
     45     if(lc[x]!=0) fa[lc[x]]=y;
     46     fa[x]=fa[y];
     47     if(y==lc[fa[y]]) lc[fa[y]]=x;
     48     else rc[fa[y]]=x;
     49     fa[y]=x; lc[x]=y;
     50     update(x); update(y);
     51 }
     52 void splay(LL x,LL s){
     53     LL p;
     54     while(fa[x]!=s){
     55         p=fa[x];
     56         if(fa[p]==s){
     57             if(x==lc[p]) r_rotate(x);
     58             else l_rotate(x);
     59             break; 
     60         }
     61         if(x==lc[p]){
     62             if(p==lc[fa[p]]) r_rotate(p),r_rotate(x);
     63             else r_rotate(x),l_rotate(x);
     64         }
     65         else{
     66             if(p==rc[fa[p]]) l_rotate(p),l_rotate(x);
     67             else l_rotate(x),r_rotate(x);
     68         }
     69     }
     70     if(s==0) root=x;
     71     update(x);
     72 }
     73 LL find(LL v){//查找在这棵树中键值为v的节点 
     74     LL x=root;
     75     while(x!=0){
     76         if(v<key[x]) x=lc[x];
     77         else if(v>key[x]) x=rc[x];
     78         else if(v==key[x]){
     79             splay(x,0);
     80             return x;
     81         }
     82     }
     83     return -1;
     84 }
     85 void New_node(LL &x,LL fath,LL v){//建立新节点 
     86     x=++tot;
     87     lc[x]=rc[x]=0; siz[x]=1;
     88     fa[x]=fath;
     89     key[x]=v;
     90 }
     91 void insert(LL v){//插入新节点 
     92     if(root==0){
     93         New_node(rc[0],0,v);
     94         root=tot;
     95         return ;
     96     }
     97     LL p,x=root;
     98     while(x!=0){
     99         p=x;
    100         if(v<=key[x]) siz[x]++,x=lc[x];
    101         else siz[x]++,x=rc[x];
    102     }
    103     if(v<=key[p]) New_node(lc[p],p,v);
    104     else New_node(rc[p],p,v);
    105     splay(tot,0);
    106 }
    107 LL getmax(LL x){//找到以x为根的最大值 
    108     if(rc[x]!=0) return getmax(rc[x]);
    109     return x;
    110 }
    111 LL getmin(LL x){//找到以x为根的最小值 
    112        if(lc[x]!=0) return getmin(lc[x]);
    113     return x;
    114 }
    115 void Delete(LL v){
    116     LL x=find(v);
    117     LL pp=getmax(lc[x]);
    118     LL nn=getmin(rc[x]);
    119     if(lc[x]==0||rc[x]==0){
    120         if(lc[x]==0&&rc[x]==0){
    121             root=0; rc[0]=0; 
    122             return ;
    123         }
    124         if(lc[x]==0){
    125             rc[0]=rc[x]; fa[rc[x]]=0; root=rc[x]; rc[x]=0;
    126             siz[x]=1;
    127             return ;
    128         }
    129         else{
    130             rc[0]=lc[x]; fa[lc[x]]=0; root=lc[x]; lc[x]=0;
    131             siz[x]=1;
    132             return ;
    133         }
    134     }
    135     splay(pp,0);
    136     splay(nn,root);
    137     fa[lc[nn]]=0; siz[lc[nn]]=1; lc[nn]=0;
    138     update(nn); update(pp);
    139 }
    140 LL succ(LL rt,LL v){//返回比 v大的最小的数 
    141     if(rt==0) return v;
    142     if(v>=key[rt]) return succ(rc[rt],v);
    143     else{
    144         LL ans=succ(lc[rt],v);  
    145         if(ans==v) return key[rt];
    146         return ans;
    147     }
    148 }
    149 int main(){
    150     scanf("%lld%lld",&N,&M);
    151     if(M<N){
    152         printf("-1");
    153         return 0;
    154     }
    155     for(LL i=1;i<=N;i++) scanf("%lld%lld",&cow[i].a,&cow[i].b);
    156     for(LL i=1;i<=M;i++) scanf("%lld%lld",&gra[i].a,&gra[i].b);
    157     sort(cow+1,cow+N+1,cmp); sort(gra+1,gra+M+1,cmp2);
    158     for(LL i=1,j=1;i<=N;i++){
    159         while(gra[j].b>=cow[i].b&&j<=M)
    160             insert(gra[j++].a);
    161         if(siz[root]==0){printf("-1"); return 0;}
    162         if(find(cow[i].a)!=-1){
    163             ANS+=cow[i].a;
    164             Delete(cow[i].a);
    165         }
    166         else{
    167             LL num=succ(root,cow[i].a);
    168             ANS+=num; 
    169             Delete(num);
    170         }
    171     }
    172     printf("%lld",ANS);
    173     return 0;
    174 }
  • 相关阅读:
    HDU 4864 Task(贪心值得学习)
    使程序在Linux下后台运行
    KMP算法
    优先队列的使用
    POJ 2761 Feed the dogs(树状数组求区间第K大)
    HDU 3584 Cube (三维树状数组)
    HDU 1892 See you~ (二维树状数组)
    POJ 1195 Mobile phones(二维树状数组)
    HDU 1166 敌兵布阵 (树状数组和线段树解法)
    POj 1703 Find them, Catch them(关系并查集)
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/5186896.html
Copyright © 2011-2022 走看看