• D2. Dances (Hard Version) Codeforces Round 905 (Div. 2)


    Problem - D2 - Codeforces

    题目大意:有两个长度为n的数组a,b,给出一个数m,每次操作要删除a和b中的一个数然后将a,b按任意顺序排序,要求用最小的操作次数使对于任意的i都有a[i]最小操作次数的和。

    2<=n<=1e5.1<=m<=1e9;1<=a[i],b[i]<=1e9

    思路:首先考察每次操作的最优策略是什么,首先数字顺序肯定两个数组都要最小到大排序,要让a小于b,那么应该优先删除a中最大的数和b中最小的数,要删除多少数可以从1到n二分枚举,因为删除更多的数肯定更容易满足条件,符合单调性,这样我们就得到了a[1]固定为某个数时的答案。

            我们令a[1]=1时的答案为ans,在我们增大a[1]到m的过程中,可以发现区别就是可能之前a[1]不用删,增大后要删,那么答案相差就是0或1,且操作次数是随着a[1]增大而增加的,所以我们可以二分枚举1到m找到答案+1的位置,也就是找到一个x使得a[1]=x时得到的答案与ans不同,这样前边的数量*ans后边的数量*(ans+1)就是最终的答案。

    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. ll n;
    8. int a[N];
    9. int temp[N];
    10. int b[N];
    11. bool check(int x)
    12. {
    13. for (int i = 1; i <= n - x; i++)
    14. {
    15. if (a[i] >= b[x + i])
    16. {//a中的前n-x个数和b中后n-x个数做对比
    17. return 0;
    18. }
    19. }
    20. return 1;
    21. }
    22. void init()
    23. {
    24. }
    25. void solve()
    26. {
    27. cin >> n;
    28. int m;
    29. cin >> m;
    30. init();
    31. a[1] = 1;
    32. for (int i = 2; i <= n; i++)
    33. {
    34. cin >> a[i];
    35. temp[i] = a[i];//复制一份a数组
    36. }
    37. for (int i = 1; i <= n; i++)
    38. {
    39. cin >> b[i];
    40. }
    41. sort(a + 1, a + n + 1);
    42. sort(b + 1, b + n + 1);//将a和b按从小到大的顺序排序
    43. int l = 0, r = n, mid;
    44. ll ans;
    45. while (l <= r)
    46. {//从1到n二分枚举操作次数
    47. mid = (l + r) >> 1;
    48. if (check(mid))
    49. {
    50. ans = mid;
    51. r = mid - 1;
    52. }
    53. else
    54. {
    55. l = mid + 1;
    56. }
    57. }
    58. l = 1, r = m;
    59. ll ans2 = m + 1;//初始化为m+1,没有枚举到答案不同的地方时,答案就是ans*m
    60. while (l <= r)
    61. {//二分枚举a[1],找到操作次数改变的第一个位置
    62. for (int i = 1; i <= n; i++)
    63. {
    64. a[i] = temp[i];
    65. }
    66. mid = (l + r) >> 1;
    67. a[1] = mid;
    68. sort(a + 1, a + n + 1);
    69. if (!check(ans))
    70. {
    71. ans2 = mid;
    72. r = mid - 1;
    73. }
    74. else
    75. {
    76. l = mid + 1;
    77. }
    78. }
    79. cout << (ans2-1)*ans+(m-ans2+1)*(ans+1);//两个操作次数分别乘以他们的数量
    80. cout << '\n';
    81. }
    82. int main()
    83. {
    84. ios::sync_with_stdio(false);
    85. cin.tie(0);
    86. int t;
    87. cin >> t;
    88. //t = 1;
    89. while (t--)
    90. {
    91. solve();
    92. }
    93. return 0;
    94. }

  • 相关阅读:
    Git 如何去使用
    【常驻进程内存优化】开机5分钟后常驻进程(Persistent)占用内存大小≤xxxMB,不达标
    vue-qr插件使用 报错You may need an appropriate loader to handle this file type
    国际经济合作名词解释
    Electron之单例+多窗口
    C++ 基础与深度分析 Chapter8 动态内存管理(动态内存基础、智能指针、相关问题)
    SCS【10】单细胞转录组之差异表达分析 (Monocle 3)
    手机提词器有哪些?简单介绍这一款
    业务流程管理包括什么
    基于ssm的设备信息管理系统
  • 原文地址:https://blog.csdn.net/ashbringer233/article/details/134005948