zoukankan      html  css  js  c++  java
  • 堆排序

    输入一个长度为n的整数数列,从小到大输出前m小的数。

    输入格式

    第一行包含整数n和m。

    第二行包含n个整数,表示整数数列。

    输出格式

    共一行,包含m个整数,表示整数数列中前m小的数。

    数据范围

    1mn1051≤m≤n≤105,
    11091≤数列中元素≤109

    输入样例:

    5 3
    4 5 1 3 2
    

    输出样例:

    1 2 3

    ##############################################################
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int N = 1e5+10;
     5 int arr[N], cnt;
     6 int n, m;
     7 //O(lgn)
     8 void down(int index){
     9     int tmp = index;
    10     //在父节点和孩子节点中找到最小的那个节点
    11     if(index*2 <= cnt && arr[index*2] < arr[tmp]) tmp = index*2;
    12     if(index*2+1 <= cnt && arr[index*2+1] < arr[tmp]) tmp = index*2+1;
    13     if(tmp != index){
    14         swap(arr[tmp],arr[index]);
    15         down(tmp);
    16     }
    17 }
    18 
    19 int main(){
    20     cin >> n >> m;
    21     cnt = n;
    22     for(int i = 1; i<= n;++i)cin >> arr[i];
    23     for(int i = n >> 1;i;--i)down(i);//建堆,从最底层之上的一层开始down,因为最底层的没有意义,此处复杂度O(n)
    24     while(m--){
    25         cout << arr[1] << " ";
    26         arr[1] = arr[cnt--];
    27         down(1);
    28     }
    29     return 0;
    30 }
    View Code

     

    模拟堆

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

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

    现在要进行N次操作,对于所有第2个操作,输出当前集合的最小值。

    输入格式

    第一行包含整数N。

    接下来N行,每行包含一个操作指令,操作指令为”I x”,”PM”,”DM”,”D k”或”C k x”中的一种。

    输出格式

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

    每个结果占一行。

    数据范围

    1N1051≤N≤105
    109x109−109≤x≤109
    数据保证合法。

    输入样例:

    8
    I -10
    PM
    I -10
    D 1
    C 2 8
    I 6
    PM
    DM
    

    输出样例:

    -10
    6
     1 #include <iostream>
     2 #include <algorithm>
     3 #include <string.h>
     4 using namespace std;
     5 
     6 const int N = 1e5+10;
     7 
     8 int arr[N];
     9 int Size;
    10 int m;
    11 int k_index[N];//表示第k个插入到堆数组中的下标的映射
    12 int index_k[N];//表示堆数组中下标到第k个插入的映射
    13 
    14 void heap_swap(int x, int y){
    15     swap(k_index[index_k[x]], k_index[index_k[y]]);            
    16     swap(index_k[x], index_k[y]);
    17     swap(arr[x], arr[y]);
    18 }
    19 
    20 void down(int p){
    21     int t = p;
    22     if(p*2 <= Size && arr[p*2] < arr[t]) t = p*2;
    23     if(p*2+1 <= Size && arr[p*2+1] < arr[t]) t = p*2 + 1;
    24     if(t != p){
    25         heap_swap(p,t);
    26         down(t);
    27     }
    28 }
    29 /*void up(int u)
    30 {
    31     while (u / 2 && arr[u] < arr[u / 2])
    32     {
    33         heap_swap(u, u / 2);
    34         u >>= 1;
    35     }
    36 }
    37 */
    38 void up(int p){
    39     if(p <= Size && p / 2 > 0 && arr[p>>1] > arr[p]){
    40         heap_swap(p / 2,p);    
    41         up(p / 2); 
    42     }  
    43 }
    44 
    45 int main(){
    46     int n;
    47     cin >> n;
    48     while(n--){
    49         string op;
    50         int k, x;
    51         cin >> op;
    52         if(op == "I"){
    53             cin >> x;
    54             ++Size;
    55             ++m;
    56             k_index[m] = Size;
    57             index_k[Size] = m;
    58             arr[Size] = x;
    59             up(Size);
    60         }
    61         if(op == "PM")cout << arr[1] << endl;
    62         if(op == "DM"){
    63             heap_swap(1,Size);
    64             --Size;
    65             down(1);
    66         }
    67         if(op == "D"){
    68             cin >> k;
    69             int t = k_index[k];
    70             heap_swap(t,Size);
    71             --Size;
    72             up(t);
    73             down(t);
    74         }
    75         if(op == "C"){
    76             cin >> k >> x;
    77             arr[k_index[k]] = x;
    78             up(k_index[k]);
    79             down(k_index[k]);
    80         }
    81     }
    82     return 0;
    83 }
    View Code

    end

  • 相关阅读:
    C# 获取 存储过程 返回值
    C# System.Data.OracleClient requires Oracle client software version 8.1.7 or greater
    C# oracle 日期型字段,使用参数传值时,遇到ORA-01810: format code appears twice错误
    C# oracle to_date 日期型 参数传值
    windows2003两台服务器,局域网之间不能互相访问
    windows2003服务器,时间每隔1小时自动同步一次
    sqlserver 服务器主体 无法在当前安全上下文下访问数据库
    电商设计V1(一):软件工程设计
    Maven使用教程三:maven的生命周期及插件机制详解
    JVM 学习笔记二 :JVM内存区域
  • 原文地址:https://www.cnblogs.com/sxq-study/p/12228319.html
Copyright © 2011-2022 走看看