• C. Medium Design Codeforces Round 904 (Div. 2)


    Problem - C - Codeforces

    题目大意:有一个长为m的数组初始全为0,有n个区间[li,ri],每选择一个区间就要令区间内所有数+1,要求选择一些区间,使得数组的最大值-最小值最大,求这个差值

    1<=n<=1e5;1<=m<=1e9

    思路:我们设取得最大值的位置是i,我们要让这个最大值最大,那么所有包含这个位置的区间都要选,并设这些区间去掉重合部分后组成的大区间为[L,R],那么这个区间内最小值的取值位置一定是L或R,因为假如最小值的取值位置在LR里面,那么可以把这个位置左边或右边的区间删掉同时另一边的最大值仍然等于原来的最大值,最小值又变成了新的大区间的端点。

            所以当整个数组最小值在[L,R]外边时,这时答案就等于最大值,如果在L或R,那么需要把以L为左端点的区间删掉或把以R为右端点的区间删掉,这些区间对最大值和最小值的贡献都是1,所以删掉后ma-mi不变,两种情况取最大值即可。

            考虑如何求区间最大值,因为这题m的范围不能开数组,所以我们用对组数组记录区间的端点,左端点就是{位置,1},右端点就是{位置+1,-1},然后将所有端点从小到大排序,遍历这总共最多2e5个端点,维护前缀和同时维护最大值即可。

    1. //#include<__msvc_all_public_headers.hpp>
    2. #include
    3. using namespace std;
    4. typedef long long ll;
    5. const ll MOD = 1e9 + 7;
    6. const int N = 1e5 + 5;
    7. int n;
    8. pair<int, int>a[N];
    9. void init()
    10. {
    11. }
    12. void solve()
    13. {
    14. cin >> n;
    15. int m;
    16. cin >> m;
    17. init();
    18. for (int i = 1; i <= n; i++)
    19. {
    20. int x, y;
    21. cin >> x >> y;
    22. a[i] = { x,y };
    23. }
    24. vectorint,int>>num1,num2;
    25. ll ma = 0;
    26. for (int i = 1; i <= n; i++)
    27. {
    28. if (a[i].first != 1)
    29. {//左端点不是1的
    30. num1.push_back({ a[i].first,1 });//左端点是+1
    31. num1.push_back({ a[i].second + 1,-1 });//右端点是-1
    32. }
    33. if (a[i].second != m)
    34. {//右端点不是m的
    35. num2.push_back({ a[i].first,1 });
    36. num2.push_back({ a[i].second + 1,-1 });
    37. }
    38. }
    39. sort(num1.begin(), num1.end());//从小到大排序
    40. sort(num2.begin(), num2.end());
    41. int las = 0;//当前的下标
    42. ll cnt = 0;//差分数组前缀和
    43. for (int i = 0; i < num1.size(); i++)
    44. {//遍历所有端点
    45. if (num1[i].first > las)
    46. {//下标移动后维护最大值
    47. ma = max(ma, cnt);
    48. }
    49. cnt += num1[i].second;
    50. las = num1[i].first;
    51. }
    52. las = 0, cnt = 0;
    53. for (int i = 0; i < num2.size(); i++)
    54. {
    55. if (num2[i].first > las)
    56. {
    57. ma = max(ma, cnt);
    58. }
    59. cnt += num2[i].second;
    60. las = num2[i].first;
    61. }
    62. cout << ma;
    63. cout << '\n';
    64. }
    65. int main()
    66. {
    67. ios::sync_with_stdio(false);
    68. cin.tie(0);
    69. int t;
    70. cin >> t;
    71. //t = 1;
    72. while (t--)
    73. {
    74. solve();
    75. }
    76. return 0;
    77. }

  • 相关阅读:
    机器学习必修课 - 交叉验证 Cross-Validation
    Win11共享文件打不开怎么办?Win11共享文件打不开的解决方法
    (JavaSE) String类
    操作系统(二 )| 进程控制 进程状态 进程描述 进程控制 进程同步互斥
    计算机毕业设计SSMjspm基于框架的影视分享平台【附源码数据库】
    Linux网络通信(线程池和线程池版本的服务器代码)
    故障分析 | MySQL 节点宕机分析一例
    如何实现一个分布式锁
    金仓数据库 KingbaseES与Oracle的兼容性说明(2. 数据类型)
    让EXCEL VBA支持鼠标滚轮,vb6 IDE鼠标滚轮插件原理
  • 原文地址:https://blog.csdn.net/ashbringer233/article/details/133975803