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\n", 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.哈希表

 

第三讲:搜索与图论

 

第四讲:数学知识

 

第五讲:动态规划

 

第六讲:贪心

 

posted @ 2021-04-27 12:28  rookie161  阅读(1313)  评论(0编辑  收藏  举报