• 区间查找,二分,思维


    Contest (nefu.edu.cn)

    区间查找

    Problem:C
    Time Limit:1000ms
    Memory Limit:65535K

    Description

    给定两个长度为 n 的数组 A 和 B,对于所有的 ai+bj 从小到大排序,并输出第 L 个到第 R 个数。

    Input

    第一行三个数 n,L,R。然后分别输入a[i]和b[i];
    

    Output

    输出第L个数到第R个数!

    Sample Input

    2 1 4
    1 3
    2 4
    

    Sample Output

    3 5 5 7 
    注意最后的数后面带1个空格!
    

    Hint

    1<=n<1e5;1<=L<=R<=n^2;R-L<1e5;1<=a[i],b[i]<=1e9;

    解析:

     这道题与P1631 序列合并,思维,优先队列-CSDN博客道题相近

    这不过需要用二分将第L下的数求出来

    需要注意:

    这里二分求得是第L-1小的数+1

    为什么不直接求第L小的数呢?

    直接求第L小的数可能会因为数组第L小得数相邻得数与他一样而求成比他大1的数,这样后需处理就会很麻烦,所以直接求第L-1小的数+1

    具体看代码:
     

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. using namespace std;
    16. typedef long long LL;
    17. const int N = 1e5 + 5;
    18. LL n, l, r;
    19. LL a[N], b[N],to[N];
    20. typedef struct st {
    21. LL first, second;
    22. }st;
    23. int check(LL num, LL lim) {
    24. LL cnt = 0;
    25. int p = n;
    26. for (int i = 1; i <= n; i++) {
    27. while (p >= 1 && a[i] + b[p] >= num)p--;//慢慢体会,非常妙
    28. cnt += (LL)p;
    29. }
    30. return cnt >= lim;
    31. }
    32. LL bin(LL L, LL R, LL lim) {
    33. LL mid, ret = 0;
    34. while (L <= R) {
    35. mid = L + (R - L) / 2;
    36. if (check(mid,lim)) {
    37. ret = mid;
    38. R = mid - 1;
    39. }
    40. else {
    41. L = mid + 1;
    42. }
    43. }
    44. return ret;
    45. }
    46. bool operator>(const st& a, const st& b) {
    47. return a.first > b.first;
    48. }
    49. int main() {
    50. scanf("%lld%lld%lld", &n, &l, &r);
    51. for (int i = 1; i <= n; i++) {
    52. scanf("%lld", &a[i]);
    53. }
    54. for (int i = 1; i <= n; i++) {
    55. scanf("%lld", &b[i]);
    56. }
    57. sort(a + 1, a + 1 + n);
    58. sort(b + 1, b + 1 + n);
    59. LL lnum=bin(0,(LL)2e9+5, l - 1);//二分结果为第L个数字加1
    60. LL cnt = 0;
    61. for (int i = 1,p=n; i <= n; i++) {
    62. to[i] = ((i == 1) ? n : (to[i - 1]));
    63. while (to[i] > 0 && a[i] + b[to[i]] >= lnum)--to[i];//慢慢体会,非常妙
    64. cnt += (LL)to[i];
    65. }
    66. for (LL i = l; i <= min(cnt, r); ++i)printf("%lld ", lnum - 1);//特殊情况处理,如,1,5,5,5,5,5,9,求第5到第7个数
    67. l = cnt + 1;
    68. priority_queue < st, vector, greater>q;
    69. for(int i = 1; i <= n; i++) {
    70. if (to[i] < n)q.push({ (a[i] + b[++to[i]]), (i) });
    71. }
    72. int t;
    73. for (LL i = l; i <= r; i++) {
    74. printf("%lld ", q.top().first);
    75. t = q.top().second;
    76. q.pop();
    77. if(to[t]
    78. q.push({ a[t] + b[++to[t]], t });
    79. }
    80. return 0;
    81. }

  • 相关阅读:
    猿创征文|我这样看国产数据库TBase
    安化云台山风景区超详细旅行计划
    基于STM32G431嵌入式学习笔记——七、定时器定时
    每日五问(java)
    数据库系统原理与应用教程(044)—— MySQL 查询(六):使用 LIMIT 选项实现分页查询
    python-0007-django模版
    【C语言】自定义类型:联合体和枚举
    使用数据库实现缓存功能
    2、ARM处理器概论
    Spring循环依赖解决
  • 原文地址:https://blog.csdn.net/Landing_on_Mars/article/details/133823057