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.哈希表

 

第三講:搜索與圖論

 

第四講:數學知識

 

第五講:動態規划

 

第六講:貪心

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM