zoukankan      html  css  js  c++  java
  • [USACO07DEC]美食的食草动物Gourmet Grazers

    ~~~题面~~~

    题解:

      首先观察题面,直觉上对于一头奶牛,肯定要给它配pi和qi符合条件的草中两者尽量低的草,以节省下好草给高要求的牛。

      实际上这是对的,但观察到两者尽量低这个条件并不明确,无法用于判断,因此要考虑一些其他的方法。

      首先我们把牛和草都放在一个数组里,然后按照口感给它们排序。这样对于任意一头牛而言,口感符合要求的就只有在它前面的草。

      排完序后,我们只需要在任意一头牛之前找到一个还没有被分配的,价格最低的符合要求的草即可。

      为什么这样就不用考虑口感尽量低这个条件了呢?

      因为对于后面的任意一只牛而言,在它前面的草的口感值大于要求,因此不管前面的牛怎么选择,剩下的草都是符合口感要求的,因此此时再去对口感值做限制就毫无意义了。

      所以我们只需要在它前面的草中筛选出大于价格要求的,最便宜的草即可。

      如果没有大于价格要求这一条件,显然我们可以用堆,但是由于这个条件限制,堆无法实现。

      因此我们可以考虑用平衡树来实现它。

      用STL是最简单的,当然也可以自己手写。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define R register int
      4 #define AC 220000
      5 #define LL long long
      6 
      7 int n, m, cnt;
      8 LL ans;
      9 
     10 struct node{
     11     int cost, taste;
     12     bool who;
     13 }p[AC];
     14 
     15 struct splay_tree{
     16     int root, tot, go;
     17     int son[AC][2], father[AC], cnt[AC], Size[AC], val[AC];
     18     
     19     inline void update(int x)
     20     {
     21         Size[x] = Size[son[x][0]] + Size[son[x][1]] + cnt[x];
     22     }
     23     
     24     void rotate(int x)
     25     {
     26         int y = father[x];
     27         int z = father[y];
     28         int k = (son[y][1] == x);
     29         father[x] = z;
     30         son[z][son[z][1] == y] = x;
     31         father[son[x][k ^ 1]] = y;
     32         son[y][k] = son[x][k ^ 1];
     33         father[y] = x;
     34         son[x][k ^ 1] = y;
     35         update(y), update(x);
     36     }
     37     
     38     void splay(int x, int goal)
     39     {
     40         if(!x) return ;
     41         while(father[x] != goal)
     42         {
     43             int y = father[x], z = father[y];
     44             if(z != goal) 
     45                 (son[y][0] == x) ^ (son[z][0] == y) ? rotate(x) : rotate(y);
     46             rotate(x);
     47         }
     48         update(x);
     49         if(!goal) root = x;
     50     }
     51     
     52     void find(int x, int w)//找到这个点的前驱,并splay到root
     53     {
     54         if(!x) return ;
     55         if(val[x] >= w)
     56         {
     57             if(!go || val[x] < val[go]) go = x;
     58             find(son[x][0], w);
     59         } 
     60         else find(son[x][1], w);
     61     }
     62     
     63     int found(int k)//找根的前驱后继
     64     {
     65         int now = root;
     66         now = son[now][k];
     67         while(son[now][k ^ 1]) now = son[now][k ^ 1];
     68         return now;
     69     }
     70     
     71     void get(int x)
     72     {
     73         go = 0, find(root, x);
     74         if(!go) 
     75         {
     76             printf("-1
    ");
     77             exit(0);
     78         }
     79         splay(go, 0);
     80         ans += val[go];
     81         if(cnt[go] > 1) 
     82         {
     83             --cnt[go];
     84             update(go);
     85             return ;
     86         }
     87         int before = found(0), behind = found(1);
     88         if(!before && !behind) root = 0;
     89         else if(!before) root = son[root][1], father[root] = 0;
     90         else if(!behind) root = son[root][0], father[root] = 0;
     91         else splay(before, 0), splay(behind, before);
     92         son[behind][0] = 0;
     93     }
     94     
     95     void insert(int x)//插入一个点
     96     {
     97         int now = root, fa = 0;
     98         while(now && val[now] != x)
     99         {
    100             fa = now;
    101             now = son[now][x > val[now]];
    102         }
    103         if(now) cnt[now] ++;
    104         else
    105         {
    106             now = ++ tot;
    107             if(fa) son[fa][x > val[fa]] = now;
    108             father[now] = fa;
    109             val[now] = x;
    110             cnt[now] = Size[now] = 1;
    111             if(fa) update(fa);
    112         }
    113         splay(now, 0);
    114     }
    115 }s;
    116 
    117 inline int read()
    118 {
    119     int x = 0;char c = getchar();
    120     while(c > '9' || c < '0') c = getchar();
    121     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    122     return x;
    123 }
    124 
    125 inline bool cmp(node a, node b)
    126 {
    127     if(a.taste != b.taste) return a.taste > b.taste;
    128     else return a.cost > b.cost;
    129 }
    130 
    131 void pre()
    132 {
    133     int a, b;
    134     n = read(), m = read();
    135     for(R i = 1; i <= n; i ++)
    136     {
    137         a = read(), b = read();
    138         p[++cnt] = (node){a, b, 0}; 
    139     }
    140     for(R i = 1; i <= m; i ++)
    141     {
    142         a = read(), b = read();
    143         p[++cnt] = (node){a, b, 1};
    144     }    
    145     sort(p + 1, p + cnt + 1, cmp);
    146 //    for(R i = 1; i <= cnt; i ++)
    147     //    printf("%d %d %d
    ", p[i].cost, p[i].taste, p[i].who);
    148 }
    149 
    150 void work()
    151 {
    152     for(R i = 1; i <= cnt; i ++)
    153         if(!p[i].who) s.get(p[i].cost);
    154         else s.insert(p[i].cost);
    155     printf("%lld
    ", ans);
    156 }
    157 
    158 int main()
    159 {
    160 //    freopen("in.in", "r", stdin);
    161     pre();
    162     work();
    163 //    fclose(stdin);
    164     return 0;
    165 }
    View Code

     

  • 相关阅读:
    leetcode 13. Roman to Integer
    python 判断是否为有效域名
    leetcode 169. Majority Element
    leetcode 733. Flood Fill
    最大信息系数——检测变量之间非线性相关性
    leetcode 453. Minimum Moves to Equal Array Elements
    leetcode 492. Construct the Rectangle
    leetcode 598. Range Addition II
    leetcode 349. Intersection of Two Arrays
    leetcode 171. Excel Sheet Column Number
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9615541.html
Copyright © 2011-2022 走看看