-
个人简介
提供的如下收费服务,有问题请联系管理员(UID=31) i@undefined.moe
- 绑定自定义域名(在右侧【高级功能】面板中操作)
- 更换 Logo
- 更改名称
- 批量注册账户
中缀表达式求值 (+-*/^)
#include <iostream> #include <stack> #include <string> #include <map> #include <cmath> #define int long long using namespace std; stack <char> fu; stack <int> num; string st; map <char, int> mp {{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}, {'^', 3}}; void init (string str) { for (int i = 0; i < str.size (); i ++) { if ((str[i] == '-' || str[i] == '+') && (i == 0 || str[i - 1] == '(')) { st += '0'; } if (str[i] == '(' && str[i - 1] == ')') { st += '*'; } st += str[i]; } } void sum () { int b = num.top(); num.pop(); int a = num.top(); num.pop(); char c = fu.top(); fu.pop(); int x; switch (c) { case '+' : num.push (a + b); break; case '-' : num.push (a - b); break; case '*' : num.push (a * b); break; case '/' : num.push (a / b); break; case '^' : num.push (pow (a, b)); break; default : break; } return ; } signed main() { string str; cin >> str; init (str); //cout << st << endl << endl; for (int i = 0; i < st.size (); i ++) { if (st[i] >= '0' && st[i] <= '9') { int j = i, x = 0; while (st[j] >= '0' && st[j] <= '9') //多位数; x = x * 10 + (st[j ++ ] - '0'); num.push (x); i = j - 1; } else if (st[i] == '(') { fu.push (st[i]); } else if (st[i] == ')') { while (fu.top() != '(') { //算括号内的; sum (); } fu.pop (); //弹出 "("; } else { while (fu.size() && fu.top() != '(' && mp[fu.top ()] >= mp[st[i]]) { sum (); } //栈不空 且 下一个符号不是左括号 且 当前优先级比栈顶优先级低; fu.push (st[i]); } } while (fu.size()) { sum (); } cout << num.top() << endl; return 0; }
dijkstra求最短路
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 510; int n, m; int g[N][N], dis[N], st[N]; int dijkstra () { memset (dis, 0x3f, sizeof dis); dis[1] = 0; for (int i = 1; i <= n; i ++) { int t = -1; for (int j = 1; j <= n; j ++) { if (st[j] == 0 && (t == -1 || dis[t] > dis[j])) { t = j; } } st[t] = true; for (int j = 1; j <= n; j ++) { dis[j] = min (dis[j], dis[t] + g[t][j]); } } if (dis[n] == 0x3f3f3f3f) { return -1; } return dis[n]; } int main () { cin >> n >> m; memset (g, 0x3f, sizeof g); while (m --) { int a, b, c; cin >> a >> b >> c; g[a][b] = min (g[a][b], c); //判断重边; } int t = dijkstra (); cout << t << endl; return 0; }
加一个堆优化
#include <iostream> #include <cstring> #include <algorithm> #include <queue> using namespace std; const int N = 1000010; typedef pair <int, int> PII; int n, m; int h[N], w[N], e[N], ne[N]; int dis[N], st[N]; int idx; void add (int a, int b, int c) { e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++; } int dijkstra () { memset (dis, 0x3f, sizeof dis); dis[1] = 0; priority_queue <PII, vector <PII>, greater <PII> > p; p.push ({0, 1}); while (!p.empty ()) { auto t = p.top (); p.pop (); int ver = t.second, dit = t.first; if (st[ver]) { continue; } st[ver] = true; for (int i = h[ver]; i != -1; i = ne[i]) { int j = e[i]; if (dis[j] > dit + w[i]) { dis[j] = dit + w[i]; p.push ({dis[j], j}); } } } if (dis[n] == 0x3f3f3f3f) { return -1; } return dis[n]; } int main () { cin >> n >> m; memset (h, -1, sizeof h); while (m --) { int a, b, c; cin >> a >> b >> c; add (a, b, c); } int t = dijkstra (); cout << t << endl; return 0; }
bellman-ford求最短路
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 510, M = 10010; int n, m, k; int dis[N], ba[N]; struct no { int a, b, w; }ed[M]; int bellman_ford () { memset (dis, 0x3f, sizeof dis); dis[1] = 0; for (int i = 1; i <= k; i ++) { memcpy (ba, dis, sizeof dis); for (int j = 1; j <= m; j ++) { int a = ed[j].a, b = ed[j].b, w = ed[j].w; dis[b] = min (dis[b], ba[a] + w); } } if (dis[n] > 0x3f3f3f3f / 2) return -100000; return dis[n]; } int main () { cin >> n >> m >> k; for (int i = 1; i <= m; i ++) { int a, b, w; cin >> a >> b >> w; ed[i] = {a, b, w}; } int t = bellman_ford (); if (t == -100000) cout << "impossible\n"; else cout << t << endl; return 0; }
SPFA求最短路
#include <iostream> #include <cstring> #include <algorithm> #include <queue> using namespace std; const int N = 1000010; typedef pair <int, int> PII; int n, m; int h[N], w[N], e[N], ne[N]; int dis[N], st[N]; int idx; void add (int a, int b, int c) { e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++; } int spfa () { queue <int> q; memset (dis, 0x3f, sizeof dis); dis[1] = 0; q.push (1); st[1] = 1; //当时这个点在队列中 while (!q.empty ()) { int t = q.front (); q.pop (); st[t] = false; for (int i = h[t]; i != -1; i = ne[i]) { int j = e[i]; if (dis[j] > dis[t] + w[i]) { dis[j] = dis[t] + w[i]; if (!st[j]) { q.push (j); st[j] = 1; } } } } if (dis[n] == 0x3f3f3f3f) return -100000; else return dis[n]; } int main () { cin >> n >> m; memset (h, -1, sizeof h); while (m --) { int a, b, c; cin >> a >> b >> c; add (a, b, c); } int t = spfa (); if (t == -100000) cout << "impossible\n"; else cout << t << endl; return 0; }
SPFA判断负环
#include <iostream> #include <cstring> #include <algorithm> #include <queue> using namespace std; const int N = 1000010; typedef pair <int, int> PII; int n, m; int h[N], w[N], e[N], ne[N]; int dis[N], st[N], cn[N]; int idx; void add (int a, int b, int c) { e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++; } int spfa () { queue <int> q; for (int i = 1; i <= n; i ++) { st[i] = 1; q.push (i); } while (!q.empty ()) { int t = q.front (); q.pop (); st[t] = false; for (int i = h[t]; i != -1; i = ne[i]) { int j = e[i]; if (dis[j] > dis[t] + w[i]) { dis[j] = dis[t] + w[i]; cn[j] = cn[t] + 1; if (cn[j] > n) return 1; if (!st[j]) { q.push (j); st[j] = 1; } } } } return 0; } int main () { cin >> n >> m; memset (h, -1, sizeof h); while (m --) { int a, b, c; cin >> a >> b >> c; add (a, b, c); } if (spfa ()) cout << "Yes\n"; else cout << "No\n"; return 0; }
欧拉筛素数模板
#include <iostream> #include <cstring> using namespace std; const int N = 100000100; const int n = 10000010; int pr[N], f[N], cnt = 0; //f[i] 为 1 表示是素数,否则为非素数。 //pr[i] 用来存素数。 void euler (int n) { //筛到n。 memset (f, 1, sizeof f); //开始默认全为素数。 f[1] = 0; //1不是素数。 for (int i = 2; i <= n; i ++) { if (f[i]) { //没有筛掉: pr[++ cnt] = i; //i成为下一个素数。 } for (int j = 1; j <= cnt && pr[j] * i <= n; j ++) { //从pr[1]开始,逐个枚举已知的素数。 //期望pr[j] 为 (i * pr[j]) 的最小质因子。 //当然,i肯定比pr[j]大,因为pr[j]是在i之前得出的。 f[i * pr[j]] = 0; //标记为非素数。 if (i % pr[j] == 0) { //i中含有pr[j]这个因子: break; //退出,保证线性复杂度。 } } } } int main () { ios :: sync_with_stdio (0); int q; cin >> q; euler(n); while (q --) { int k; cin >> k; cout << pr[k] << endl; } return 0; }
DFS框架
void dfs (int k) { if (/*所有空都已填完*/) { //判断最优解、记录答案 return ; } for (/*枚举这个空能填的选项*/) { if (/*这个选项是合法的*/) { //记录下这个空(保存现场) dfs (k + 1); //取消这个空(恢复现场) } } } //******************************************************************** void dfs (int k) { for (/*枚举这个空能填的选项*/) { if (/*满足条件*/) { //保存结果 if (/*到目的地*/) { //输出解 } else { dfs (k + 1); } //回复结果(回溯) } } }
BFS框架
void bfs() { //初始化,初始状态存入队列; //队列首指针head=0,尾指针tail=1; while(head<=tail) { //指针head后移一位,指向待扩展节点 for(int i=1;i<=max;i++) //max为产生子节点的规则数 { if(/*子节点符合条件*/) { //tail++,把新节点存入队列 if(/*新节点与原条件重复*/) { //删除该节点(取消入队,tail--;) else if(/*新节点是目标节点*/) //输出并退出 } } } } }
快速幂
#include <bits/stdc++.h> #define int long long using namespace std; int ksm (int a, int b, int p) { int res = 1; while (b) { if (b & 1) res = res * a % p; b >>= 1; a = a * a % p; } } main () { int a, b, p; cin >> a >> b >> p; cout << ksm (a, b, p) << endl; return 0; }
快速排序
#include <bits/stdc++.h> using namespace std; const int N = 100010; int n, q[N]; void qsort (int q[], int l, int r) { if (l >= r) return ; int x = q[l], i = l - 1, j = r + 1; while (i < j) { do i ++; while (q[i] < x); do j --; while (q[j] > x); if (i < j) swap (q[i], q[j]); } qsort (q, l, j); qsort (q, j + 1, r); } int main () { cin >> n; for (int i = 1; i <= n; i ++) cin >> q[i]; qsort (q, 1, n); for (int i = 1; i <= n; i ++) cout << q[i] << ' '; return 0; }
归并排序
#include <bits/stdc++.h> using namespace std; const int N = 1000010; int n, q[N], tmp[N]; void msort (int q[], int l, int r) { if (l >= r) return ; int mid = l + r >> 1; msort (q, l ,mid); msort (q, mid + 1, r); int k = 0, i = l, j = mid + 1; while (i <= mid && j <= r) { if (q[i] <= q[j]) tmp[k ++] = q[i ++]; else tmp[k ++] = q[j ++]; } while (i <= mid) tmp[k ++]= q[i ++]; while (j <= r) tmp[k ++]= q[j ++]; for (i = l, j = 0; i <= r; i ++, j ++) q[i] = tmp[j]; } main () { cin >> n; for (int i = 1; i <= n; i ++) cin >> q[i]; msort (q, 1, n); for (int i = 1; i <= n; i ++) cout << q[i] << ' '; return 0; }
二分查找数的范围
#include <bits/stdc++.h> using namespace std; const int N = 100010; int n, m, q[N]; int main () { cin >> n >> m; for (int i = 0; i < n; i ++) cin >> q[i]; while (m --) { int x; cin >> x; int l = 0, r = n - 1; while (l < r) { int mid = l + r >> 1; if (q[mid] >= x) r = mid; else l = mid + 1; } if (q[l] != x) cout << "-1 -1" << endl; else { cout << l << ' '; int l = 0, r = n - 1; while (l < r) { int mid = l + r + 1 >> 1; if (q[mid] <= x) l = mid; else r = mid - 1; } cout << l << endl; } } return 0; }
#include <iostream> #include <algorithm> using namespace std; int dep[1000000], cx[1000000]; struct no { int a; }a[1000000]; int n, c; bool cmp (no a, no b) { if (cx[a.a] == cx [b.a]) return dep[a.a] < dep[b.a]; else return cx[a.a] > cx[b.a]; } int main () { cin >> n >> c; for (int i = 1; i <= n; i ++) { cin >> a[i].a; if (dep[a[i].a] == 0) { dep[a[i].a] = i; } cx [a[i].a] ++; } sort (a + 1, a + 1 + n, cmp); for (int i = 1; i <= n; i ++) { cout << a[i].a << ' '; } return 0; }
二分图的最大匹配
#include <bits/stdc++.h> using namespace std; void Ios () { ios :: sync_with_stdio (false); cin.tie (); cout.tie (); } const int N = 510, M = 100010; int n1, n2, m; int h[N], e[M], ne[M], idx; int mac[N]; bool st[N]; int add (int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx ++; } bool find (int x) { for (int i = h[x]; i != -1; i = ne[i]) { int j = e[i]; if (! st[j]) { st[j] = true; if (mac[j] == 0 || find (mac[j])) { mac[j] = x; return true; } } } return false; } int main () { Ios (); cin >> n1 >> n2 >> m; memset (h, -1, sizeof h); while (m --) { int a, b; cin >> a >> b; add (a, b); } int res = 0; for (int i = 1; i <= n1; i ++) { memset (st, false, sizeof st); if (find (i)) res ++; } cout << res << endl; return 0; }
高精度加法
#include <bits/stdc++.h> using namespace std; vector<int> add (vector<int> &A, vector<int> &B) { if (A.size () < B.size ()) return add(B, A); vector <int> C; int t = 0; for (int i = 0; i < A.size (); i ++ ) { t += A[i]; if (i < B.size()) t += B[i]; C.push_back(t % 10); t /= 10; } if (t) C.push_back(t); return C; } int main () { string a, b; vector<int> A, B; cin >> a >> b; for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0'); for (int i = b.size() - 1; i >= 0; i -- ) B.push_back(b[i] - '0'); auto C = add(A, B); for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i]; cout << endl; return 0; }
高精度减法
#include <bits/stdc++.h> using namespace std; bool cmp (vector <int> &a, vector <int> &b) { if (a.size () != b.size ()) { return a.size () > b.size (); } for (int i = a.size (); i >= 0; i --) if (a[i] != b[i]) return a[i] > b[i]; return true; } vector<int> sub (vector<int> &a, vector<int> &b) { vector <int> c; for (int i = 0, t = 0; i < a.size (); i ++) { t = a[i] - t; if (i < b.size ()) t -= b[i]; c.push_back ((t + 10) % 10); if (t < 0) t = 1; else t = 0; } while (c.size () > 1 && c.back () == 0) c.pop_back (); return c; } int main () { string a, b; vector<int> A, B; cin >> a >> b; for (int i = a.size() - 1; i >= 0; i -- ) A.push_back (a[i] - '0'); for (int i = b.size() - 1; i >= 0; i -- ) B.push_back (b[i] - '0'); if (cmp (A, B)) { auto C = sub (A, B); for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i]; } else { auto C = sub (B, A); cout << "-"; for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i]; } cout << endl; return 0; }
高精度乘法(A*b)
#include <bits/stdc++.h> using namespace std; vector <int> mul(vector <int> & A, int b) { vector <int> C; int t = 0; for (int i = 0; i < A.size(); i ++) { t += A[i] * b; C.push_back(t % 10); t /= 10; } while (t) { C.push_back(t % 10); t /= 10; } while (C.size() > 1 && C.back() == 0) C.pop_back(); return C; } int main() { string a; int b; cin >> a >> b; vector <int> A; for (int i = a.size() - 1; i >= 0; i --) A.push_back(a[i] - '0'); auto C = mul(A, b); for (int i = C.size() - 1; i >= 0; i --) { cout << C[i]; } return 0; }
高精度除法
#include <bits/stdc++.h> using namespace std; vector <int> div(vector <int> & A, int b, int &r) { vector <int> C; r = 0; for (int i = A.size () - 1; i >= 0; i --) { r = r * 10 + A[i]; C.push_back (r / b); r %= b; } reverse (C.begin(), C.end ()); while (C.size()>1&&C.back()==0) C.pop_back(); return C; } int main() { string a; int b; cin >> a >> b; vector <int> A; for (int i = a.size() - 1; i >= 0; i --) A.push_back(a[i] - '0'); int r; auto C = div(A, b, r); for (int i = C.size() - 1; i >= 0; i --) { cout << C[i]; } cout << endl << r << endl; return 0; }
#include <iostream> #include <map> using namespace std; int n, m, ans = 0, a[2000010], z[2000010]; map <int, int> mp; int main () { cin >> n >> m; for (int i = 1; i <= n; i ++) { cin >> a[i]; z[i] = z[i - 1] + a[i]; mp[z[i - 1]] ++; ans += mp[z[i] - m]; } cout << ans << endl; return 0; }
AC自动机
#include <bits/stdc++.h> using namespace std; const int N = 10010, S = 55, M = 1000010; int n; int tr[N * S][26]; int cnt[N * S]; int idx; char str[M]; int q[N * S]; int ne[N * S]; void insert() { int p = 0; for (int i = 0; str[i]; i++) { int t = str[i] - 'a'; if (!tr[p][t]) tr[p][t] = ++idx; p = tr[p][t]; } cnt[p]++; } void build() { int hh = 0, tt = -1; for (int i = 0; i < 26; i++) if (tr[0][i]) q[++tt] = tr[0][i]; while (hh <= tt) { int t = q[hh++]; for (int i = 0; i < 26; i++) { int c = tr[t][i]; if (!c) continue; int j = ne[t]; while (j && !tr[j][i]) j = ne[j]; if (tr[j][i]) j = tr[j][i]; ne[c] = j; q[++tt] = c; } } } int main() { int T; cin >> T; while (T--) { memset(tr, 0, sizeof tr); memset(cnt, 0, sizeof cnt); memset(ne, 0, sizeof ne); idx = 0; cin >> n; for (int i = 0; i < n; i++) { scanf("%s", str); insert(); } build(); scanf("%s", str); int res = 0; for (int i = 0, j = 0; str[i]; i++) { int t = str[i] - 'a'; while (j && !tr[j][t]) j = ne[j]; if (tr[j][t]) j = tr[j][t]; int p = j; while (p) { res += cnt[p]; cnt[p] = 0; p = ne[p]; } } cout << res << endl; } return 0; }
树的节点计数
#include <iostream> using namespace std; const int N = 50010; int n, x, y; int now[2 * N], pre[2 * N], son[2 * N], tot, deep[N]; void put (int x, int y) { pre[++ tot] = now[x]; now[x] = tot; son[tot] = y; } void dfs (int dep, int fa) { deep[dep] = 1; for (int i = now[dep]; i; i = pre[i]) { if (son[i] != fa) { dfs (son[i], dep); deep[dep] += deep[son[i]]; } } } int main () { cin >> n; for (int i = 1; i < n; i ++) { cin >> x >> y; put (x, y); put (y, x); } dfs (1, 0); for (int i = 1; i <= n; i ++) { cout << deep[i] - 1<< endl; } }
cout<<fixed<<setprecision(n)<<a;
Sublime Text :
1.打开 软件;
2.打开 => => ;
3.将源代码改为:
{ "shell_cmd": "g++ \"${file}\" -o \"${file_path}/${file_base_name}\" -Wall -std=c++11 -Wextra -g", "file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$", "working_dir": "${file_path}", "selector": "source.c, source.c++", "variants": [ { "name": "Run", "shell_cmd" : "start cmd /c \"\"${file_path}/${file_base_name}\" & pause\"" }, { "name": "RunInCommand", "shell_cmd" : "g++ \"${file}\" -o \"${file_path}/${file_base_name}\" -Wall -std=c++11 -Wextra -g && start cmd /c \"\"${file_path}/${file_base_name}\" & echo. & echo -------------------------------- & echo Process exited after seconds with return value 0 & pause\"" }, { "name": "Debug", "shell_cmd" : "start cmd /c \"gdb \"${file_path}/${file_base_name}\"\"" } ] }
4.将文件名改为:
aa.sublime-build
;5.打开 => ,进入键位设置;
6.按下 Ctrl+F 快捷键,在搜索栏输入 f7;
7.将高亮代码 f7 下方的 Ctrl+B 改为 F11,并保存;
8.最后,新建一个源代码,将其命名为 xx.cpp,就能编译了。。。
用位运算实现加减乘除:
1. 加法:
// 递归写法 int add(int num1, int num2) { if (num2 == 0) return num1; int sum = num1 ^ num2; int carry = (num1 & num2) << 1; return add(sum, carry); } // 迭代写法 int add(int num1, int num2) { int sum = num1 ^ num2; int carry = (num1 & num2) << 1; while (carry != 0) { int a = sum; int b = carry; sum = a ^ b; carry = (a & b) << 1; } return sum; }
扩展欧几里得算法求ax+by=c:
void ojld (int a, int b) { if (b == 0) { x = 1, y = 0; return ; } ojld (b, a % b); t1 = x, t2 = y; x = t2, y = t1 - (a / b) * t2; }
快速幂:
int qmi (int a, int b, int p) { int ans = 1; while (b) { if (b & 1) { ans = (a * a) % p; b --; } b /= 2; a = a * a % p; } return ans; }
三种筛素数的方法:
-
- 筛法:
if (n <= 1) return 0; for (int i = 2; i * i <= n; i ++) if (n % i == 0) return 0; return 1;
-
- 埃式筛法:
int p[1000010]; for (int i = 2; i <= sqrt (n); i ++) { if (p[i] == 0) { for (int j = 2; j <= n / i; j ++) { p[i * j] = 1; } } } if (p[n] == 1) return 0; else return 1;
-
- 欧拉筛法:
// 筛 1 ~ N 中的素数 ok[1] = 1; for (int i = 2; i <= N; i ++) { if (!ok[i]) { pr[++ t] = i; } for (int j = 1; j <= t && i * pr[j] <= N; j ++) { ok[i * pr[j]] = 1; if (i % pr[j] == 0) { break; } } continue; } for (int i = 1; i <= 100; i ++) { if (!ok[i]) { cout << i << ' '; } }
// 筛 1 ~ N 中与N互质的数 void euler2 () { phi[1] = 1; for (int i = 2; i <= N; i++) { if (!isprime[i]) { prime[++tot] = i; phi[i] = i - 1; } for (int j = 1; j <= tot; j++) { if (i * prime[j] > N) break; isprime[i * prime[j]] = 1; if (i % prime[j] == 0) { phi[i * prime[j]] = phi[i] * prime[j]; break; } else phi[i * prime[j]] = phi[i] * (prime[j] - 1); } } for (int i = 1; i <= N; i ++) { cout << phi[i] << ' '; } }
准备工作
- 比赛前一天晚上请准备好你的各种证件以及笔等基本工具(我的身边就有因为没带准考证而爆炸的例子)。
- CSP 是允许带食品和饮料的,所以可以带一些水和巧克力等进入考场补充体力。
- 比赛开始前请先调整你的屏幕分辨率到你喜欢的大小。
- 比赛开始前请把编译器的字体调为你平时惯用的字体。
- 在不影响视野的情况下,请将字号尽可能调大,方便查错(特别是一些毒瘤模拟或搜索)
- 比赛开始前多敲敲键盘,顺手的键盘都需要敲打一番(提前熟悉键盘的各个键——经常会与自己学校的不一样,在自己学校比赛的请忽略这句话),这段时间里你可以先打好快读快写、头文件等模板。
- 根据个人需求并在合理时间内待在考场里,熟悉一下气氛。
参考文献 https://www.scratch5.com/scratch#621914581663660938942 https://www.acwing.com/blog/content/829/ https://www.acwing.com/blog/content/798/ https://www.cnblogs.com/ljy-endl/p/11768512.html https://www.cnblogs.com/dysyn1314/p/13934854.html https://www.cnblogs.com/codingxu/p/15433809.html https://www.cnblogs.com/milkycoffee/p/csp-s-2021-zhuyi.html https://www.cnblogs.com/skip1978/p/11861737.html
-
通过的题目
-
最近活动
-
最近编写的题解
-
Stat
-
Rating
题目标签
- 模拟
- 13
- NOIp 普及组
- 10
- CSP-J
- 6
- 枚举
- 6
- 暴力
- 6
- 2019
- 3
- 2021
- 3
- 字符串
- 3
- 数论
- 3
- 数学
- 3
- 2004
- 2
- 2005
- 2
- NOIp 提高组
- 2
- 排序
- 2
- 树状数组
- 2
- 1998
- 1
- 1999
- 1
- 2002
- 1
- 2006
- 1
- 2008
- 1