其他分享
首页 > 其他分享> > 金发姑娘和N头牛

金发姑娘和N头牛

作者:互联网

金发姑娘和N头牛

你可能听过关于金发姑娘和三只熊的经典故事。

然而,鲜为人知的是,金发姑娘最终成了一个农民。

在她的农场中,她的牛棚里有$N$奶牛。

不幸的是,她的奶牛对温度相当敏感。

对于奶牛$i$,使其感到舒适的温度为$A_{i}…B_{i}$。

如果金发姑娘将牛棚的恒温器的温度$T$设置为$T < A_{i}$,奶牛就会觉得冷,并会产出$X$单位的牛奶。

如果她将恒温器的温度$T$设置在$A_{i} \leq T \leq B_{i}$,奶牛就会感到舒适,并会产出$Y$单位的牛奶。

如果她将恒温器的温度$T$设置为$T > B_{i}$,奶牛就会觉得热,并会产出$Z$单位的牛奶。

正如所期望的那样,$Y$的值始终大于$X$和$Z$。

给定$X$,$Y$,$Z$以及每头奶牛感到舒适的温度范围,请计算通过合理设定恒温器温度,金发姑娘可获得的最大产奶量。

恒温器温度可设置为任何整数。

输入格式

第一行包含四个整数$N$,$X$,$Y$,$Z$。

接下来$N$行,每行包含两个整数$A_{i}$和$B_{i}$。

输出格式

输出可获得的最大产奶量。

数据范围

$1 \leq N \leq 20000$,
$0 \leq X, Y, Z \leq 1000$,
$0 \leq A_{i} \leq B_{i} \leq {10}^{9}$

输入样例:

4 7 9 6
5 8
3 4
13 20
7 10

输出样例:

31

样例解释:

金发姑娘可以将恒温器温度设置为$7$或$8$,这样会让奶牛$1$和$4$感到舒适,奶牛$2$感到热,奶牛$3$感到冷。

共可获得$31$单位牛奶。

 

解题思路

  题目意思大概就是,在一个无限长的数轴上给定一个区间,然后在该区间上的任取一个值(温度),对答案(产量)的贡献为$y$。如果在这个区间的左部分取值的话,则对答案的贡献为$x$。如果在这个区间的右部分取值的话,则对答案的贡献为$z$。

  等价于给每个区间都加上对应的数值,可以联想到差分。 

  这题给的$N$的数据范围很小,但值域却很大。实际上我们会用到的下标的值不会超过$2N$个,因此可以进行离散化。

  用差分数组得到原数组的话,其实是求差分数组的前缀和。值为$0$的位置其实可以不用管,因为$0$对前缀和没有影响。所以求最大值的时候可以把所有的$0$全部跳过。这意味着求前缀和的时候,只需要用所有出现过的数就可以了。因此我们只需要存区间的左右端点的下标就可以了。

  这里可以用map实现,$key$是下标,$value$是$x$或$y$或$z$。并且在遍历的时候,map会实现$key$的有序排序,因此可以用map来实现离散化。

  AC代码如下:

 1 #include <cstdio>
 2 #include <map>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 const int INF = 2e9;
 7 
 8 map<int, int> mp;
 9 
10 int main() {
11     int n, x, y, z;
12     scanf("%d %d %d %d", &n, &x, &y, &z);
13     for (int i = 0; i < n; i++) {
14         int left, right;
15         scanf("%d %d", &left, &right);
16 
17         mp[-INF] += x, mp[left] -= x;
18         mp[left] += y, mp[right + 1] -= y;
19         mp[right + 1] += z, mp[INF] -= z;
20     }
21 
22     int sum = 0, ret = 0;
23     for (auto &it : mp) {
24         sum += it.second;
25         ret = max(ret, sum);
26     }
27     printf("%d", ret);
28 
29     return 0;
30 }

  用map实现的话常数会比较大,运行效率没有手写高,因此下面给出手写实现离散化的方式。

  AC代码如下:

 1 #include <cstdio>
 2 #include <vector>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 const int N = 2e4 + 10, INF = 2e9;
 7 
 8 vector<int> alls;
 9 int l[N], r[N], b[2 * N];
10 
11 int find(int x) {
12     int left = 0, right = alls.size() - 1;
13     while (left < right) {
14         int mid = left + right >> 1;
15         if (alls[mid] >= x) right = mid;
16         else left = mid + 1;
17     }
18 
19     return left;
20 }
21 
22 int main() {
23     int n, x, y, z;
24     scanf("%d %d %d %d", &n, &x, &y, &z);
25     for (int i = 0; i < n; i++) {
26         scanf("%d %d", l + i, r + i);
27         alls.push_back(l[i]), alls.push_back(r[i] + 1);
28     }
29     alls.push_back(-INF), alls.push_back(INF);
30 
31     sort(alls.begin(), alls.end());
32     alls.erase(unique(alls.begin(), alls.end()), alls.end());
33 
34     for (int i = 0; i < n; i++) {
35         int left = find(l[i]), right = find(r[i] + 1);
36         b[0] += x, b[left] -= x;
37         b[left] += y, b[right] -= y;
38         b[right] += z, b[alls.size() - 1] -= z;
39     }
40 
41     int sum = 0, ret = 0;
42     for (int i = 0; i < alls.size() - 1; i++) {
43         sum += b[i];
44         ret = max(ret, sum);
45     }
46     printf("%d", ret);
47 
48     return 0;
49 }

 

参考资料

  AcWing 1952. 金发姑娘和 N 头牛(寒假每日一题2022):https://www.acwing.com/video/3667/

标签:金发,right,头牛,int,姑娘,ret,leq,alls,left
来源: https://www.cnblogs.com/onlyblues/p/15865495.html