[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

 

原文地址:https://www.cnblogs.com/ww3113306/p/9615541.html