• 堆排序(838,839)(堆中的元素编号与插入堆的插入序号相映射)


    838. 堆排序

    输入一个长度为 n

    的整数数列,从小到大输出前 m

    小的数。

    输入格式

    第一行包含整数 n

    和 m

    第二行包含 n

    个整数,表示整数数列。

    输出格式

    共一行,包含 m

    个整数,表示整数数列中前 m

    小的数。

    数据范围

    1≤m≤n≤105


    1≤数列中元素≤109

    输入样例:

    1. 5 3
    2. 4 5 1 3 2

    输出样例:

    1 2 3
    

     

    1. #include <iostream>
    2. #include <algorithm>
    3. using namespace std;
    4. const int maxn = 1e5+10;
    5. int heap[maxn],sz;
    6. void down(int l,int h)
    7. {
    8. int par=l,chi=2*par;
    9. while(chi<=sz)
    10. {
    11. if(chi < sz && heap[chi+1]<heap[chi])
    12. ++chi;
    13. if(heap[chi] < heap[par])
    14. {
    15. swap(heap[chi],heap[par]);
    16. par=chi;
    17. chi=2*par;
    18. }
    19. else
    20. break;
    21. }
    22. }
    23. void create()
    24. {
    25. for(int i=sz/2;i>0;--i)
    26. down(i,sz);
    27. }
    28. int top()
    29. {
    30. return heap[1];
    31. }
    32. void pop()
    33. {
    34. swap(heap[1],heap[sz]);
    35. --sz;
    36. down(1,sz);
    37. }
    38. int main()
    39. {
    40. int n,m;
    41. cin >> n >> m;
    42. for(int i=1;i<=n;++i) cin >> heap[i];
    43. sz=n;
    44. create();
    45. for(int i=0;i<m;++i)
    46. {
    47. cout << top() << ' ';
    48. pop();
    49. }
    50. return 0;
    51. }

    839. 模拟堆

    维护一个集合,初始时集合为空,支持如下几种操作:

    1. I x,插入一个数 x
    • PM,输出当前集合中的最小值;
    • DM,删除当前集合中的最小值(数据保证此时的最小值唯一);
    • D k,删除第 k
    • 个插入的数;
    • C k x,修改第 k
    • 个插入的数,将其变为 x

      现在要进行 N

      次操作,对于所有第 2

      个操作,输出当前集合的最小值。

      输入格式

      第一行包含整数 N

      接下来 N

      行,每行包含一个操作指令,操作指令为 I xPMDMD kC k x 中的一种。

      输出格式

      对于每个输出指令 PM,输出一个结果,表示当前集合中的最小值。

      每个结果占一行。

      数据范围

      1≤N≤105


      −109≤x≤109


      数据保证合法。

      输入样例:

      1. 8
      2. I -10
      3. PM
      4. I -10
      5. D 1
      6. C 2 8
      7. I 6
      8. PM
      9. DM

      输出样例:

      1. -10
      2. 6

     

    * I x,插入一个数 x : heap[++sz]=x,up(1,sz);
     * PM,输出当前集合中的最小值: heap[1];
     * DM,删除当前集合中的最小值 : swap(heap[1],heap[sz]),--sz;
     * D k,删除第 k个插入的数:swap(heap[k],heap[sz]),--sz; 但此时要注意,第k个
     * 插入的数并不是堆中第k号位的元素;
     * C k x,修改第 k个插入的数,将其变为 x;heap[k]=x; 此时第k个插入的数也不是
     * 堆中第k号位的元素;
     *
     * 在插入元素或者删除元素或者修改元素的值,都需要调整堆的元素位置,以满足
     * 堆的特性;
     *
     * 因此需要找出第k个插入的数在堆中的位置编号;同时也要反映出堆中第u号位的数
     * 是第几个插进来的数;所以我们需要开两个映射数组来反映出这两种信息;
     *
     * 在进行堆的元素交换的时候,我们需要把映射数组的信息也进行交换,即:
     *   void heap_swap(int u,int v)
         {
            swap(ph[hp[u]],ph[hp[v]]);
            swap(hp[u],hp[v]);
            swap(heap[u],heap[v]);
         }
     
     画一根二叉树模拟一下就能理解了;

    1. /**
    2. * I x,插入一个数 x : heap[++sz]=x,up(1,sz);
    3. * PM,输出当前集合中的最小值: heap[1];
    4. * DM,删除当前集合中的最小值 : swap(heap[1],heap[sz]),--sz;
    5. * D k,删除第 k个插入的数:swap(heap[k],heap[sz]),--sz; 但此时要注意,第k个
    6. * 插入的数并不是堆中第k号位的元素;
    7. * C k x,修改第 k个插入的数,将其变为 x;heap[k]=x; 此时第k个插入的数也不是
    8. * 堆中第k号位的元素;
    9. *
    10. * 在插入元素或者删除元素或者修改元素的值,都需要调整堆的元素位置,以满足
    11. * 堆的特性;
    12. *
    13. * 因此需要找出第k个插入的数在堆中的位置编号;同时也要反映出堆中第u号位的数
    14. * 是第几个插进来的数;所以我们需要开两个映射数组来反映出这两种信息;
    15. *
    16. * 在进行堆的元素交换的时候,我们需要把映射数组的信息也进行交换,即:
    17. * void heap_swap(int u,int v)
    18. {
    19. swap(ph[hp[u]],ph[hp[v]]);
    20. swap(hp[u],hp[v]);
    21. swap(heap[u],heap[v]);
    22. }
    23. 画一根二叉树模拟一下就能理解了;
    24. */
    25. #include <iostream>
    26. #include <algorithm>
    27. using namespace std;
    28. const int maxn = 1e5+10;
    29. int heap[maxn],sz;
    30. int ph[maxn],hp[maxn];
    31. //堆的第u号和第v号元素进行交换,要把ph数组和hp数组对应的元素也进行交换,
    32. //以能够为后续的删除或者修改操作找到正确的修改位置;
    33. void heap_swap(int u,int v)
    34. {
    35. swap(ph[hp[u]],ph[hp[v]]);
    36. swap(hp[u],hp[v]);
    37. swap(heap[u],heap[v]);
    38. }
    39. void down(int l,int r) //对[l,r]内的值进行向下调整
    40. {
    41. int par=l,chi=2*par;
    42. while(chi<=r)
    43. {
    44. if(chi<r && heap[chi+1]<heap[chi])
    45. ++chi;
    46. if(heap[chi] < heap[par])
    47. {
    48. heap_swap(chi,par);
    49. par=chi;
    50. chi=2*par;
    51. }
    52. else
    53. break;
    54. }
    55. }
    56. void up(int l,int r)//对[l,r]内的值进行向上调整
    57. {
    58. int chi=r,par=chi/2;
    59. while(par>=l && heap[chi]<heap[par])
    60. {
    61. heap_swap(chi,par);
    62. chi=par;
    63. par=chi/2;
    64. }
    65. }
    66. int main()
    67. {
    68. int n,idx=0;
    69. cin >> n;
    70. while (n -- )
    71. {
    72. string op;
    73. int k,x;
    74. cin >> op;
    75. if(op == "I")
    76. {
    77. cin >> x;
    78. heap[++sz]=x;
    79. ++idx;
    80. ph[idx]=sz;
    81. hp[sz]=idx;
    82. up(1,sz);
    83. }
    84. else if(op == "PM")
    85. cout << heap[1] << endl;
    86. else if(op == "DM")
    87. {
    88. heap_swap(1,sz);
    89. --sz;
    90. down(1,sz);
    91. }
    92. else if(op == "D")
    93. {
    94. cin >> k;
    95. k=ph[k];
    96. heap_swap(k,sz);
    97. --sz;
    98. down(k,sz);
    99. up(1,k);
    100. }
    101. else
    102. {
    103. cin >> k >> x;
    104. k=ph[k];
    105. heap[k]=x;
    106. down(k,sz);
    107. up(1,k);
    108. }
    109. }
    110. return 0;
    111. }

  • 相关阅读:
    VAEGAN:理解 VAE 与 GAN【图像生成】
    微信小程序——video视频全屏展示
    js修改函数this指向的三种常用方法总结
    SDN实战团技术分享(三十八):DPDK助力NFV与云计算
    LeetCode_双指针_中等_633.平方数之和
    从-99打造Sentinel高可用集群限流中间件
    1141 PAT Ranking of Institutions
    华为配置直连三层组网直接转发示例
    C#【必备技能篇】Release下的pdb文件有什么用,是否可以删除?
    现代控制理论课程实验三:一阶倒立摆的LQR控制器设计
  • 原文地址:https://blog.csdn.net/qq_51825761/article/details/126854092