zoukankan      html  css  js  c++  java
  • AcWing算法基础课

    第一讲:基础算法

    第二讲:数据结构

    1.单链表

    2.双链表

    3.栈

    4.队列

    5.单调栈

    6.单调队列

    7.KMP

    8.Trie

    9.并查集

    10.堆

    838. 堆排序 

    题目:

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

    输入格式

    第一行包含整数 n 和 m。

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

    输出格式

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

    数据范围

    1mn105
    1109

    输入样例:

    5 3
    4 5 1 3 2
    

    输出样例:

    1 2 3

    分析:

     1 # 堆
     2 
     3 堆是一个完全二叉树。
     4 
     5 性质:每个节点都满足小于等于它的左右两边的节点。
     6 
     7 存储:1号节点为根节点,x的左儿子:`2x`,x的右儿子:`2x+1`
     8 
     9 
    10 
    11 操作
    12 
    13 把节点往下移
    14 
    15 将根节点大于左儿子和右儿子中的最小值,将根节点与左右儿子中最小的那个交换位置。然后一直交换到不能交换为止。
    16 
    17 ```cpp
    18 void down(){
    19     
    20 }
    21 ```
    22 
    23 把节点往上移
    24 
    25 某个数变小后,每次与父节点进行比较就好了,如果比父节点小的话,就要和父节点进行交换
    26 
    27 ```cpp
    28 void up(){
    29     
    30 }
    31 ```
    32 
    33 如何手写一个堆:
    34 
    35 1.插入一个数
    36 
    37 2.求集合当中的最小值
    38 
    39 3.删除最小值
    40 
    41 4.删除任意一个元素
    42 
    43 5.修改任意一个元素
    44 
    45 
    46 
    47 1.插入一个数:
    48 
    49 在当前堆的最后面插入进去,然后进行up操作
    50 
    51 ```cpp
    52 heap[++ size] = x;
    53 
    54 up(size);
    55 ```
    56 
    57 2.求集合当中的最小值
    58 
    59 ```cpp
    60 heap[1]; 
    61 ```
    62 
    63 3.删除最小值
    64 
    65 用堆中的最后一个元素覆盖掉第一个元素,size--然后down一下
    66 
    67 一维数组删掉第一个元素比较难,但是删掉最后一个元素很简单
    68 
    69 ```cpp
    70 heap[1] = heap[size -- ];
    71 down(1);
    72 ```
    73 
    74 4.删除任意一个元素
    75 
    76 ```cpp
    77 heap[k] = heap[size]; 
    78 size -- ;
    79 down(k), up(k);
    80 ```
    81 
    82 5.修改任意一个元素
    83 
    84 ```cpp
    85 heap[k] = x; 
    86 down(k), up(k);
    87 ```
    View Code

    代码:

     1 #include <cstdio>
     2 #include <cmath>
     3 
     4 using namespace std;
     5 
     6 const int N = 100010;
     7 
     8 int n, m;
     9 int h[N], size;
    10 
    11 void down(int u)
    12 {
    13     int t = u;
    14     if ((u << 1 <= size) && h[u << 1] < h[t]) t = u << 1;
    15     if ((u << 1 | 1) <= size && h[u << 1 | 1] < h[t]) t = (u << 1 | 1);
    16     
    17     if (u != t)
    18     {
    19         swap(h[u], h[t]);
    20         down(t);
    21     }
    22 }
    23 int main()
    24 {
    25     scanf("%d%d", &n, &m);
    26     size = n;
    27     for (int i = 1; i <= n; i ++ ) scanf("%d", &h[i]);
    28     
    29     for (int i = n / 2; i >= 1; i -- ) down(i);
    30     
    31     while (m -- ) 
    32     {
    33         printf("%d ", h[1]);
    34         h[1] = h[size -- ];
    35         down(1);
    36     }
    37     
    38     return 0;
    39 }
    View Code

    839. 模拟堆

    题目:

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

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

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

    输入格式

    第一行包含整数 NN。

    接下来 NN 行,每行包含一个操作指令,操作指令为 I xPMDMD k 或 C k x 中的一种。

    输出格式

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

    每个结果占一行。

    数据范围

    1N105
    109x109
    数据保证合法。

    输入样例:

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

    输出样例:

    -10
    6

    分析:

    up和down操作

    注意ph,hp的应用,相当于指针

    ph[k] = t;第K个插入的在堆中的位置为t;

    hp[t] = k;在堆中位置为t的数是第k个插入的数

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 
     7 const int N = 100010;
     8 
     9 int cnt;
    10 int ph[N], hp[N];//ph是第k个插入的元素是几,hp是当前元素是第几个插入的
    11 int h[N];
    12 
    13 //交换当前元素的位置
    14 void heap_swap(int a, int b)
    15 {
    16     swap(ph[hp[a]], ph[hp[b]]);
    17     swap(hp[a], hp[b]);
    18     swap(h[a], h[b]);
    19 }
    20 
    21 void up(int u)
    22 {
    23     while (u / 2 && h[u] < h[u / 2]) 
    24     {
    25         heap_swap(u, u / 2);
    26         u >>= 1;
    27     }
    28 }
    29 
    30 void down(int u)
    31 {
    32     int t = u;
    33     if (((u << 1) <= cnt) && h[u << 1] < h[t]) t = u << 1;
    34     if (((u << 1 | 1) <= cnt) && h[u << 1 | 1] < h[t]) t = (u << 1| 1);
    35     if (t != u)
    36     {
    37         heap_swap(t, u);
    38         down(t);
    39     }
    40 }
    41 
    42 
    43 int main()
    44 {
    45     int n, m = 0;
    46     scanf("%d", &n);
    47     
    48     while (n -- )
    49     {
    50         char op[4];
    51         int k, x;
    52         scanf("%s", op);
    53         if (!strcmp(op, "I"))
    54         {
    55             scanf("%d", &x);
    56             cnt ++;
    57             m ++;
    58             h[cnt] = x;
    59             ph[m] = cnt;
    60             hp[cnt] = m;
    61             up(cnt);
    62         }
    63         else if (!strcmp(op, "PM"))
    64         {
    65             printf("%d
    ", h[1]);
    66         }
    67         else if (!strcmp(op, "DM"))
    68         {
    69             heap_swap(1, cnt);
    70             cnt --;
    71             down(1);
    72         }
    73         else if (!strcmp(op, "D"))
    74         {
    75             scanf("%d", &k);
    76             k = ph[k];
    77             heap_swap(k, cnt);
    78             cnt --;
    79             down(k), up(k);
    80         }
    81         else 
    82         {
    83             scanf("%d%d", &k, &x);
    84             h[ph[k]] = x;
    85             down(ph[k]), up(ph[k]);
    86         }
    87     }
    88     
    89     return 0;
    90 }
    View Code

    11.哈希表

    第三讲:搜索与图论

    第四讲:数学知识

    第五讲:动态规划

    第六讲:贪心

  • 相关阅读:
    实用图片滑块,传送带,幻灯片效果【附源码】
    Canvas 示例:4种超炫的网站动画背景效果
    GOCR.js – 使用 JS 识别出图片中的文本
    Flexslider
    30款最好的 Bootstrap 3.0 免费主题和模板
    应用 CSS3 动画实现12种风格的通知提示
    Sequence.js 实现带有视差滚动特效的图片滑块
    使用QFuture类监控异步计算的结果
    Qt中的常用容器类(解释比较全面,有插图)
    QMetaEnum获取枚举元信息
  • 原文地址:https://www.cnblogs.com/Iamcookieandyou/p/14708462.html
Copyright © 2011-2022 走看看