├── 0_竞赛介绍
├── ACM竞赛技巧.md
├── CCF CSP比赛技巧.md
├── README.md
├── 信息学竞赛技巧.md
└── 蓝桥杯比赛技巧.md
├── 10_suffixarray
├── 1_suffixarray.md
├── code
│ └── 1_suffixarray.cpp
└── content.md
├── 11_expert_datastructure
├── 1_segment_tree_point.md
├── 2_segment_tree_interval.md
├── 3_binary_index_tree.md
├── 4_2d_binary_index_tree.md
├── 5_discretization.md
├── code
│ ├── 1_segment_tree_point.cpp
│ ├── 2_segment_tree_interval.cpp
│ ├── 3_binary_index_tree.cpp
│ ├── 4_2d_binary_index_tree.cpp
│ └── 5_discretization.cpp
└── content.md
├── 1_datastructure
├── 1_vector.md
├── 2_set.md
├── 3_map.md
├── 4_stack.md
├── 5_queue.md
├── 6_priority_queue.md
├── 7_disjoint.md
├── code
│ ├── 1_vector.cpp
│ ├── 2_set.cpp
│ ├── 3_map.cpp
│ ├── 4_stack.cpp
│ ├── 5_queue.cpp
│ ├── 6_priority_queue.cpp
│ └── 7_disjoint.cpp
├── content.md
├── 优先队列.cpp
├── 优先队列.md
├── 单调队列.cpp
├── 单调队列.md
├── 双端队列.cpp
├── 双端队列.md
├── 队列.cpp
└── 队列.md
├── 2_search
├── 1_queen.md
├── 2_bfs.md
├── code
│ ├── 1_queen.cpp
│ └── 2_bfs.cpp
└── content.md
├── 3_dp
├── 1_knapsack.md
├── 2_LIS.md
├── 3_LCS.md
├── 4_stage.md
├── code
│ ├── 1_knapsack.cpp
│ ├── 2_LIS.cpp
│ ├── 3_LCS.cpp
│ └── 4_stage.cpp
└── content.md
├── 4_math
├── 1_gcd.md
├── 2_prime.md
├── 3_euler.md
├── 4_exgcd.md
├── 5_binary_pow.md
├── 6_matrix_pow.md
├── code
│ ├── 1_gcd.cpp
│ ├── 2_prime.cpp
│ ├── 3_euler.cpp
│ ├── 4_exgcd.cpp
│ ├── 5_binary_pow.cpp
│ └── 6_matrix_pow.cpp
└── content.md
├── 5_tree_grpah
├── 1_adjacency_list.md
├── 2_graph_dfs.md
├── 3_graph_bfs.md
├── code
│ ├── 1_adjacency_list.cpp
│ ├── 2_graph_dfs.cpp
│ └── 3_graph_bfs.cpp
└── content.md
├── 6_short_path
├── 1_dij.md
├── 2_spfa.md
├── 3_floyd.md
├── code
│ ├── 1_dij.cpp
│ ├── 2_spfa.cpp
│ └── 3_floyd.cpp
└── content.md
├── 7_graph_algorithm
├── 1_kruskal.md
├── 2_lca.md
├── 3_topsort.md
├── 4_tarjan.md
├── code
│ ├── 1_kruskal.cpp
│ ├── 2_lca.cpp
│ ├── 3_topsort.cpp
│ └── 4_tarjan.cpp
└── content.md
├── 8_match_and_flow
├── 1_hungury.md
├── 2_dinic.md
├── 3_cost_flow.md
├── code
│ ├── 1_hungury.cpp
│ ├── 2_dinic.cpp
│ └── 3_cost_flow.cpp
└── content.md
├── 9_string_basic
├── 1_kmp.md
├── 2_exkmp.md
├── 3_trie.md
├── 4_ac.md
├── code
│ ├── 1_kmp.cpp
│ ├── 2_exkmp.cpp
│ ├── 3_trie.cpp
│ └── 4_ac.cpp
└── content.md
└── README.md
/0_竞赛介绍/ACM竞赛技巧.md:
--------------------------------------------------------------------------------
1 | # `ACM竞赛技巧`
2 |
3 | 本文主要讲一下弱校如何起步以及训练的问题
4 | - 首先要明确一个问题,大学生和高中生是不一样的,大学里的诱惑实在太多,绝大多数人都没办法一直坚持。弱校学生搞ACM更多的是想每年有几次公费出去旅游的机会罢了。
5 | - ACM竞赛和信息学竞赛不同,ACM竞赛是三个人一队的,所以如何选择另外两个队友将会直接影响到你努力的结果。
6 | - 如果你在一个弱校,但你又想在大学期间得到比较好的成绩,那么你一定要记住打死都不要去管队友的水平,自己专心训练就可以了。就算比赛的时候带两个翻译,也比1 + 1 + 1 < 1来的好。当然如果不是那么在乎成绩,那当然带着队友一起划水,一起围观神犇,一起翘课打游戏也是美滋滋的大学生活。
7 |
8 |
9 | 当你看这篇文章的时候,我假定你是一个为了省赛拿奖而努力的初学者
10 | - 在ACM竞赛中,一般会给出至少一道签到题以及一两道简单题,如何快速且一次AC简单题目将是省赛拿奖的关键。
11 | - 很多ACM比赛,题目出的区分度都不是太好,偶尔有的比赛甚至同样的题数,做的快的金牌,做的慢的铁牌,这对初学者来说是相当有利。
12 | - 初学阶段千万不要想着尽量多的学算法,而是要把代码能力练好,多做基础算法和复杂的模拟,要做到程序随心而动。不要程序写出来,连自己都没有把握写对没有。
13 | - 还是那个问题,一般情况下出题人只要没吃错药是不会出模板题的,但是还真不好说,现在的出题人都喜欢愚乐选手。这个时候你的两个划水的队友就到了体现作用的时候了,忽悠他们去整理各类题的模板,学一下怎么套模板就行了。
14 |
15 | 如果你通过基础算法侥幸拿到了省赛三等或二等,那么你的下一步目标就是拿到区域赛现场名额
16 | - 一般比较稳定的现场赛名额获取方式是通过各个赛区的网络赛,但是想进入学校排名前100甚至前90,对于一个acm刚刚起步的学校,这几乎是不可能的。因为你要面对的不仅是传统强校,别人acm发展的久的学校,退役的队员也会帮忙打,还有一些学校会请高中生帮忙打,至于关系好的学校互相探讨就是再正常不过的现象了。
17 | - 不用担心,虽然网络赛很难拿到名额,但是你可以在暑假的时候去参加邀请赛,一般来说,都能拿到一个现场赛的名额。
18 | - 最后如果你省赛、邀请赛、网络赛都没有能够拿到名额,这时候就需要你真(表)情(演)流(演)露(技)了,找一个文采好的同学,写一份声请并茂的弱校名额申请。一般举办方都会留一些名额给那些努力型选手的。至于怎么写,比如平时训练刻苦风雨无阻啊,暑期集训30天90包泡面啊之类的博取举办方的同情。
19 |
20 | 如何系统性的训练
21 | - 如果周围有acm强校,一定要厚着脸皮去蹭课旁听,特别是暑期集训,千万不能错过。
22 | - 如果是小城市,那么建议跟着本书学习,一步一个脚印,最好找两个队友一起讨论。如果书中有任何错误,欢迎及时指正。
23 |
24 | > 切记:学算法切勿心浮气躁,如果感觉状态不好,可以先调整一下状态再学习。
25 |
--------------------------------------------------------------------------------
/0_竞赛介绍/CCF CSP比赛技巧.md:
--------------------------------------------------------------------------------
1 | # `CCF CSP比赛技巧`
2 |
3 | 其实这个没什么好说的,主要记住以下几点
4 | - 做题仔细,最好写一遍暴力对拍
5 | - 注意取舍,特别是最后一题,没必要死磕全部数据的算法,第一不一定是满分
6 | - 每年都有几次的比赛,放平心态,考虑如何得分最大化
7 | - 不要去写自己平时没写过的算法
8 |
--------------------------------------------------------------------------------
/0_竞赛介绍/README.md:
--------------------------------------------------------------------------------
1 | # `竞赛介绍`
2 |
3 | - 本书主要围绕中学NOIP/NOI以及大学ACM/ICPC竞赛进行展开
4 | - 本书使用`C & C++-STL`混合编程
5 | - 本书难度不分先后
6 | - 本书旨在提供一个系统性的学习训练指南,内容会很多,帮助初学选手在脑海中建立一个竞赛算法的整体框架。
7 | - 本书亦可作为未起步或刚起步的教练指导参考书
8 |
--------------------------------------------------------------------------------
/0_竞赛介绍/信息学竞赛技巧.md:
--------------------------------------------------------------------------------
1 | # `信息学竞赛技巧`
2 |
3 |
4 | - 中学的信息学竞赛,绝大多数同学都是抱着功利性的目的来搞竞赛的。
5 | - 当然,这没有任何问题,人都是有欲望才有前进的动力,如果大家都无欲无求,剃发出家为尼为僧,社会还怎么发展进步呢?
6 | - 有的人只学了半年却比你学了一年甚至两年的成绩更好,真的完全是天赋的原因吗?或许不见得,也许是你平时的学习方法和比赛技巧出了问题。
7 |
8 |
9 | 当你看这篇文章的时候,我假定你是一个为了省一在奋斗的初学者
10 | - 对于大多数弱省而言,省一只需要会一个算法就行了,那就是暴力。
11 | - 暴力的核心是搜索,如果你想要在最短的时间内取得不错的成绩,那么就请摒弃那些纷繁复杂的算法专心学好搜索,如何找到更好的建模方式,如何剪枝,如何记忆化,如何贪心水过更多的数据将是你学习的重点。
12 | - NOIP中一般有两道送分题,或许是一个找规律,或许是一个模拟,或许仅仅是签到。遇到动态规划,直接搜,遇到数据结构,直接搜,遇到图论,直接搜,遇到数学,先搜再找规律。
13 | - 很多初学的竞赛选手有一个学习误区,就是想要快速的把所有算法都学一遍。但是就算你背会了所有的算法模板又如何呢?去赌今年的出题人会不会吃错药,出一个模板题让大家乐呵乐呵?
14 |
15 | 如果你通过暴力侥幸拿到了省一,那么你的下一步目标就是省选
16 | - 在大多数省份,省一末尾和省队之间的实力差距或许比不会算法和省一之间的差距更大。
17 | - 意识到差距之后,就不应该再想着用暴力来解决一切问题,但也不要急急忙忙的看到算法就学。首先应该静下心思考一下,也许学习一年,很大可能依然不能达到省队的水平。问一问自己是否有足够的时间,比如你现在才高一,下一次就算还是省一,你还有机会在高三翻盘。如果是这样,你就应该慢慢的扎实的学习,不要图进度。要知道看会十个算法,不如你掌握一个算法。反之,你已经高二了,你就应该考虑一下后路,而不是在竞赛上孤注一掷。进入大学之后,搞ACM竞赛你就已经赢在了起跑线上,你依然可能翻盘,毕竟4年闲暇的大学时光足够你做许多事。
18 |
19 | 如何系统性的训练
20 | - 首先应该意识到正规军和杂牌军的区别,其实可以简单的理解为省里的重点中学和山区里的学校之间的区别。
21 | - 意识到区别之后就应该想方设法地去正规军那学习或者旁听,不要嫌距离远就在网上听课甚至自己瞎琢磨,历史的经验告诉我们闭门造车离失败就不远了。
22 | - 网上搜一下附近有没有大学的ACM集训队,如果有就去找他们队长联系,跟着一起训练,有不会的就厚着脸皮问。在我看来,大学搞ACM的大多都是乐于助人的,也许ACM还有修身养性的功效吧。
23 | - 回归正题,系统性的训练分为两类,一是算法知识的不断积累,二是比赛状态的不断提升。刚开始不要盲目的去打比赛,既浪费时间又打击自信,静下心来,按照本书的算法内容不断学习,做了足够的积累之后再去打比赛查漏补缺,开阔眼界。
24 |
25 | > 切记:学算法切勿心浮气躁,如果感觉状态不好,可以先调整一下状态再学习。
26 |
--------------------------------------------------------------------------------
/0_竞赛介绍/蓝桥杯比赛技巧.md:
--------------------------------------------------------------------------------
1 | # `蓝桥杯比赛技巧`
2 |
3 | 这个也没什么好说的,自己研究历年真题去。
4 |
--------------------------------------------------------------------------------
/10_suffixarray/code/1_suffixarray.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | using namespace std;
4 | const int MAX_N = 210000;
5 | char s[MAX_N];
6 | int sa[MAX_N], t[MAX_N], t2[MAX_N], c[MAX_N], n;
7 | void build_sa(int m)
8 | {
9 | int i, *x = t, *y = t2;
10 | for (i = 0; i < m; i++) c[i] = 0;
11 | for (i = 0; i < n; i++) c[x[i] = s[i]]++;
12 | for (i = 1; i < m; i++) c[i] += c[i - 1];
13 | for (i = n - 1; i >= 0; i--) sa[--c[x[i]]] = i;
14 | for (int k = 1; k <= n; k <<= 1) {
15 | int p = 0;
16 | for (i = n - k; i < n; i++) y[p++] = i;
17 | for (i = 0; i < n; i++) if (sa[i] >= k) y[p++] = sa[i] - k;
18 |
19 | for (i = 0; i < m; i++) c[i] = 0;
20 | for (i = 0; i < n; i++) c[x[y[i]]]++;
21 | for (i = 1; i < m; i++) c[i] += c[i - 1];
22 | for (i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
23 | swap(x, y);
24 | p = 1;
25 | x[sa[0]] = 0;
26 | for (i = 1; i < n; i++) x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++;
27 | if (p >= n)
28 | break;
29 | m = p;
30 | }
31 | }
32 | int m;
33 | int cmp_suffix(char* patter, int p) {
34 | return strncmp(patter, s + sa[p], m);
35 | }
36 | int find(char* P) {
37 | m = strlen(P);
38 | if (cmp_suffix(P, 0) < 0) return -1;
39 | if (cmp_suffix(P, n - 1) > 0) return -1;
40 | int l = 0, r = n;
41 | while (l < r) {
42 | int mid = (l + r) >> 1;
43 | int res = cmp_suffix(P, mid);
44 | if (!res) {
45 | return sa[mid];
46 | }
47 | if (res < 0) {
48 | r = mid;
49 | } else {
50 | l = mid + 1;
51 | }
52 | }
53 | return -1;
54 | }
55 | int Rank[MAX_N], h[MAX_N];
56 | void get_h() {
57 | int i, j, k = 0;
58 | for (i = 0; i < n; i++) Rank[sa[i]] = i;
59 | for (i = 0; i < n; i++) {
60 | if (k) k--;
61 | if (Rank[i]) {
62 | j = sa[Rank[i] - 1];
63 | while (s[i + k] == s[j + k]) k++;
64 | h[Rank[i]] = k;
65 | }
66 | }
67 | }
68 |
69 | int main() {
70 | char ss[MAX_N];
71 | cin >> s;
72 | n = strlen(s);
73 | build_sa(131);
74 | get_h();
75 | while (cin >> ss) {
76 | cout << find(ss) << endl;
77 | }
78 | return 0;
79 | }
80 |
--------------------------------------------------------------------------------
/10_suffixarray/content.md:
--------------------------------------------------------------------------------
1 | # 后缀数组模板
2 | - 乱序
3 |
4 | |类型|标题|分数|标签|
5 | |:---:|:---:|:---:|:---:|
6 | |跟随|后缀数组模板|1||
7 |
8 |
9 | 后缀数组。
10 |
--------------------------------------------------------------------------------
/11_expert_datastructure/3_binary_index_tree.md:
--------------------------------------------------------------------------------
1 | # binary_index_tree 的使用
2 | - binary_index_tree
3 |
4 | ### 文件名
5 | binary_index_tree.cpp
6 |
7 | ### 分数
8 | 1
9 |
10 | ---
11 | ### 初始化代码
12 | ```c++
13 | #include
14 | using namespace std;
15 |
16 | int main() {
17 |
18 | return 0;
19 | }
20 | ```
21 |
22 | ---
23 | ### 第一步
24 | #### 讲解
25 | 这一节我们学习树状数组(一维)算法。
26 | 树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值(如果加入多个辅助数组则可以实现区间修改与区间查询)。
27 | 树状数组和线段树很像,但能用树状数组解决的问题,基本上都能用线段树解决,而线段树能解决的树状数组不一定能解决。相比较而言,树状数组效率要高很多。
28 | 我们先定义好要用得数据。在`main`函数上面写下
29 | ```c++
30 | const int MAX_N = 10010;
31 | int C[MAX_N];
32 | int n;
33 | ```
34 |
35 | #### 代码
36 | ```c++
37 | #include
38 | using namespace std;
39 | const int MAX_N = 10010;
40 | int C[MAX_N];
41 | int n;
42 |
43 | int main() {
44 |
45 | return 0;
46 | }
47 | ```
48 |
49 | ---
50 | ### 第二步
51 | #### 讲解
52 | 接下来输入一个数`n`。
53 | 在`main`函数里面写下
54 | ```c++
55 | cin >> n;
56 | ```
57 |
58 | #### 提示
59 | ```c++
60 | #include
61 | using namespace std;
62 | const int MAX_N = 10010;
63 | int C[MAX_N];
64 | int n;
65 |
66 | int main() {
67 | cin >> n;
68 |
69 | return 0;
70 | }
71 | ```
72 |
73 | #### 代码
74 | ```c++
75 | #include
76 | using namespace std;
77 | const int MAX_N = 10010;
78 | int C[MAX_N];
79 | int n;
80 |
81 | int main() {
82 | cin >> n;
83 |
84 | return 0;
85 | }
86 | ```
87 |
88 | ---
89 | ### 第三步
90 | #### 讲解
91 | 然后在实现`lowbit(int x)`函数。
92 | 它只保留"从低位向高位数,第一个数字1"作为运算结果。
93 | 这里用到了计算机补码的知识,也可以写成x & ((~x) + 1)。
94 | 在`main`函数里继续写下
95 | ```c++
96 | int lowbit(int x) {
97 | return x & (-x);
98 | }
99 | ```
100 |
101 | #### 提示
102 | ```c++
103 | #include
104 | using namespace std;
105 | const int MAX_N = 10010;
106 | int C[MAX_N];
107 | int n;
108 | int lowbit(int x) {
109 | return x & (-x);
110 | }
111 |
112 | int main() {
113 | cin >> n;
114 |
115 | return 0;
116 | }
117 | ```
118 |
119 |
120 | #### 代码
121 | ```c++
122 | #include
123 | using namespace std;
124 | const int MAX_N = 10010;
125 | int C[MAX_N];
126 | int n;
127 | int lowbit(int x) {
128 | return x & (-x);
129 | }
130 |
131 | int main() {
132 | cin >> n;
133 |
134 | return 0;
135 | }
136 | ```
137 |
138 |
139 | ---
140 | ### 第四步
141 | #### 讲解
142 | 接下来实现`getsum(int x)`函数。
143 | 1、令res = 0,转第二步;
144 | 2、假如x <= 0,算法结束,返回res值,否则res = res + C[x],转第三步;
145 | 3、令x = x – lowbit(x),转第二步。
146 | 在`main`函数上方写下
147 | ```c++
148 | int getsum(int x) {
149 | int res = 0;
150 | for (; x; x -= lowbit(x)) {
151 | res += C[x];
152 | }
153 | return res;
154 | }
155 | ```
156 |
157 | #### 提示
158 | ```c++
159 | #include
160 | using namespace std;
161 | const int MAX_N = 10010;
162 | int C[MAX_N];
163 | int n;
164 | int lowbit(int x) {
165 | return x & (-x);
166 | }
167 | int getsum(int x) {
168 | int res = 0;
169 | for (; x; x -= lowbit(x)) {
170 | res += C[x];
171 | }
172 | return res;
173 | }
174 |
175 | int main() {
176 | cin >> n;
177 |
178 | return 0;
179 | }
180 | ```
181 |
182 |
183 | #### 代码
184 | ```c++
185 | #include
186 | using namespace std;
187 | const int MAX_N = 10010;
188 | int C[MAX_N];
189 | int n;
190 | int lowbit(int x) {
191 | return x & (-x);
192 | }
193 | int getsum(int x) {
194 | int res = 0;
195 | for (; x; x -= lowbit(x)) {
196 | res += C[x];
197 | }
198 | return res;
199 | }
200 |
201 | int main() {
202 | cin >> n;
203 |
204 | return 0;
205 | }
206 | ```
207 |
208 |
209 | ---
210 | ### 第五步
211 | #### 讲解
212 | 接下来实现`change(int x, int c)`函数。
213 | 1、当x > n时,算法结束,否则转第二步;
214 | 2、C[x] = C[x] + c, x = x + lowbit(x)转第一步。
215 | i = i + lowbit(i)这个过程实际上也只是一个把末尾1补为0的过程。
216 | 在`main`函数上方写下
217 | ```c++
218 | void change(int x, int c) {
219 | for (; x <= n; x += x & (-x)) {
220 | C[x] += c;
221 | }
222 | }
223 | ```
224 |
225 | #### 提示
226 | ```c++
227 | #include
228 | using namespace std;
229 | const int MAX_N = 10010;
230 | int C[MAX_N];
231 | int n;
232 | int lowbit(int x) {
233 | return x & (-x);
234 | }
235 | int getsum(int x) {
236 | int res = 0;
237 | for (; x; x -= lowbit(x)) {
238 | res += C[x];
239 | }
240 | return res;
241 | }
242 | void change(int x, int c) {
243 | for (; x <= n; x += x & (-x)) {
244 | C[x] += c;
245 | }
246 | }
247 |
248 | int main() {
249 | cin >> n;
250 |
251 | return 0;
252 | }
253 | ```
254 |
255 |
256 | #### 代码
257 | ```c++
258 | #include
259 | using namespace std;
260 | const int MAX_N = 10010;
261 | int C[MAX_N];
262 | int n;
263 | int lowbit(int x) {
264 | return x & (-x);
265 | }
266 | int getsum(int x) {
267 | int res = 0;
268 | for (; x; x -= lowbit(x)) {
269 | res += C[x];
270 | }
271 | return res;
272 | }
273 | void change(int x, int c) {
274 | for (; x <= n; x += x & (-x)) {
275 | C[x] += c;
276 | }
277 | }
278 |
279 | int main() {
280 | cin >> n;
281 |
282 | return 0;
283 | }
284 | ```
285 |
286 |
287 | ---
288 | ### 第六步
289 | #### 讲解
290 | 接下来输入`n`个数并更新到树状数组的区间中。
291 | 在`main`函数里面写下
292 | ```c++
293 | for (int i = 1; i <= n; ++i) {
294 | int d;
295 | cin >> d;
296 | change(i, d);
297 | }
298 | ```
299 |
300 | #### 提示
301 | ```c++
302 | #include
303 | using namespace std;
304 | const int MAX_N = 10010;
305 | int C[MAX_N];
306 | int n;
307 | int lowbit(int x) {
308 | return x & (-x);
309 | }
310 | int getsum(int x) {
311 | int res = 0;
312 | for (; x; x -= lowbit(x)) {
313 | res += C[x];
314 | }
315 | return res;
316 | }
317 | void change(int x, int c) {
318 | for (; x <= n; x += x & (-x)) {
319 | C[x] += c;
320 | }
321 | }
322 |
323 | int main() {
324 | cin >> n;
325 | for (int i = 1; i <= n; ++i) {
326 | int d;
327 | cin >> d;
328 | change(i, d);
329 | }
330 |
331 | return 0;
332 | }
333 | ```
334 |
335 |
336 | #### 代码
337 | ```c++
338 | #include
339 | using namespace std;
340 | const int MAX_N = 10010;
341 | int C[MAX_N];
342 | int n;
343 | int lowbit(int x) {
344 | return x & (-x);
345 | }
346 | int getsum(int x) {
347 | int res = 0;
348 | for (; x; x -= lowbit(x)) {
349 | res += C[x];
350 | }
351 | return res;
352 | }
353 | void change(int x, int c) {
354 | for (; x <= n; x += x & (-x)) {
355 | C[x] += c;
356 | }
357 | }
358 |
359 | int main() {
360 | cin >> n;
361 | for (int i = 1; i <= n; ++i) {
362 | int d;
363 | cin >> d;
364 | change(i, d);
365 | }
366 |
367 | return 0;
368 | }
369 | ```
370 |
371 |
372 | ---
373 | ### 第七步
374 | #### 讲解
375 | 最后调用`getsum(i)`输出计算的结果。
376 | 在`main`函数里面继续写下
377 | ```c++
378 | for (int i = 1; i <= n; ++i) {
379 | cout << getsum(i) << " ";
380 | }
381 | ```
382 |
383 | #### 提示
384 | ```c++
385 | #include
386 | using namespace std;
387 | const int MAX_N = 10010;
388 | int C[MAX_N];
389 | int n;
390 | int lowbit(int x) {
391 | return x & (-x);
392 | }
393 | int getsum(int x) {
394 | int res = 0;
395 | for (; x; x -= lowbit(x)) {
396 | res += C[x];
397 | }
398 | return res;
399 | }
400 | void change(int x, int c) {
401 | for (; x <= n; x += x & (-x)) {
402 | C[x] += c;
403 | }
404 | }
405 |
406 | int main() {
407 | cin >> n;
408 | for (int i = 1; i <= n; ++i) {
409 | int d;
410 | cin >> d;
411 | change(i, d);
412 | }
413 | for (int i = 1; i <= n; ++i) {
414 | cout << getsum(i) << " ";
415 | }
416 | return 0;
417 | }
418 | ```
419 |
420 |
421 | #### 代码
422 | ```c++
423 | #include
424 | using namespace std;
425 | const int MAX_N = 10010;
426 | int C[MAX_N];
427 | int n;
428 | int lowbit(int x) {
429 | return x & (-x);
430 | }
431 | int getsum(int x) {
432 | int res = 0;
433 | for (; x; x -= lowbit(x)) {
434 | res += C[x];
435 | }
436 | return res;
437 | }
438 | void change(int x, int c) {
439 | for (; x <= n; x += x & (-x)) {
440 | C[x] += c;
441 | }
442 | }
443 |
444 | int main() {
445 | cin >> n;
446 | for (int i = 1; i <= n; ++i) {
447 | int d;
448 | cin >> d;
449 | change(i, d);
450 | }
451 | for (int i = 1; i <= n; ++i) {
452 | cout << getsum(i) << " ";
453 | }
454 | return 0;
455 | }
456 | ```
457 |
458 |
459 |
460 | ---
461 | ### 完成讲解
462 | 终于完成了,点击运行,看看效果吧。
463 |
464 | 聪明的你一定学会了如何使用`binary_index_tree`了。
465 |
--------------------------------------------------------------------------------
/11_expert_datastructure/5_discretization.md:
--------------------------------------------------------------------------------
1 | # discretization 的使用
2 | - discretization
3 |
4 | ### 文件名
5 | discretization.cpp
6 |
7 | ### 分数
8 | 1
9 |
10 | ---
11 | ### 初始化代码
12 | ```c++
13 | #include
14 | #include
15 | #include