• 借教室——二分、前缀和、差分


    题目

    思路

    • 当某一份订单可以满足的时候,那么他前面的所有订单都可以满足,当某一份订单不能满足的时候,那么他后面的所有订单都不能完成,所以可以使用二分查找来降低时间复杂度
    • 每次二分找到一份订单,利用二分与前缀和将当前订单以及之前的所有订单进行预处理,将每一天需要的教室数量和能够分配的数量进行比较,如果大于能够分配的教室数量,返回false,如果都满足返回true
    • 先判断m个订单是否都满足,如果有天数不满足,进行二分查找,找到第一个不满足的订单

    代码实现

    1. #include <iostream>
    2. #include <cstring>
    3. using namespace std;
    4. const int N = 1e6 + 10;
    5. typedef long long LL;
    6. int n, m;
    7. int ri[N]; // 每天能够分配的教室数量
    8. LL tmp[N]; // 前缀和数组
    9. int di[N], si[N], ti[N]; // 每天借di个,从si天开始,到ti天结束
    10. int solve(int u) // 判断到当前订单是否满足每天都有教室可以借
    11. {
    12. memset(tmp, 0, sizeof tmp); // 清空上一次的数据
    13. for(int i = 1; i<= u; i++) // 差分,处理当前订单以及之前的所有订单
    14. {
    15. tmp[si[i]] += di[i];
    16. tmp[ti[i] + 1] -= di[i];
    17. }
    18. for(int i = 1;i <= n; i++) // 前缀和,判断是否有哪天教室不够借
    19. {
    20. tmp[i] += tmp[i-1];
    21. if(tmp[i] > ri[i]) return 0;
    22. }
    23. return 1;
    24. }
    25. int main()
    26. {
    27. cin >> n >> m;
    28. for(int i = 1; i <= n; i++) cin >> ri[i];
    29. for(int i = 1;i <= m; i++) cin >> di[i] >> si[i] >> ti[i];
    30. if(solve(m)) // 先判断所有订单是否都能有教室可借
    31. {
    32. cout << 0 << endl;
    33. return 0;
    34. }
    35. int l = 0, r = m + 1; // 二分查找
    36. while(l + 1 != r)
    37. {
    38. int mid = l + r >> 1;
    39. if(solve(mid)) l = mid;
    40. else r = mid;
    41. }
    42. cout << -1 << endl;
    43. cout << r << endl;
    44. return 0;
    45. }
  • 相关阅读:
    c++新年好和通信路线(acwing)
    webpack-cli 在 webpack 打包中的作用
    如何组装一个注册中心
    SpringBoot Starter 分析及编写自己的Starter
    PyTorch 中的【高级索引】 或 【花式索引】
    windows service 服务器安装 MySQL
    始祖双碳新闻 | 2022年7月20日碳中和行业早知道
    【JUC】循环屏障CyclicBarrier详解
    重磅:成功对接杭州市版权保护管理中心!
    java八股文复习-----2024/03/04----基础
  • 原文地址:https://blog.csdn.net/m0_73197206/article/details/134429349