金发姑娘和N头牛
金发姑娘和N头牛
你可能听过关于金发姑娘和三只熊的经典故事。
然而,鲜为人知的是,金发姑娘最终成了一个农民。
在她的农场中,她的牛棚里有奶牛。
不幸的是,她的奶牛对温度相当敏感。
对于奶牛,使其感到舒适的温度为。
如果金发姑娘将牛棚的恒温器的温度设置为,奶牛就会觉得冷,并会产出单位的牛奶。
如果她将恒温器的温度设置在,奶牛就会感到舒适,并会产出单位的牛奶。
如果她将恒温器的温度设置为,奶牛就会觉得热,并会产出单位的牛奶。
正如所期望的那样,的值始终大于和。
给定,,以及每头奶牛感到舒适的温度范围,请计算通过合理设定恒温器温度,金发姑娘可获得的最大产奶量。
恒温器温度可设置为任何整数。
输入格式
第一行包含四个整数,,,。
接下来行,每行包含两个整数和。
输出格式
输出可获得的最大产奶量。
数据范围
,
,
输入样例:
4 7 9 6 5 8 3 4 13 20 7 10
输出样例:
31
样例解释:
金发姑娘可以将恒温器温度设置为或,这样会让奶牛和感到舒适,奶牛感到热,奶牛感到冷。
共可获得单位牛奶。
解题思路
题目意思大概就是,在一个无限长的数轴上给定一个区间,然后在该区间上的任取一个值(温度),对答案(产量)的贡献为。如果在这个区间的左部分取值的话,则对答案的贡献为。如果在这个区间的右部分取值的话,则对答案的贡献为。
等价于给每个区间都加上对应的数值,可以联想到差分。
这题给的的数据范围很小,但值域却很大。实际上我们会用到的下标的值不会超过个,因此可以进行离散化。
用差分数组得到原数组的话,其实是求差分数组的前缀和。值为的位置其实可以不用管,因为对前缀和没有影响。所以求最大值的时候可以把所有的全部跳过。这意味着求前缀和的时候,只需要用所有出现过的数就可以了。因此我们只需要存区间的左右端点的下标就可以了。
这里可以用map实现,是下标,是或或。并且在遍历的时候,map会实现的有序排序,因此可以用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/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/15865495.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效