基础算法
快排调用
1 2
| sort(a, a + n); sort(a, a + n, cmp);
|
二分
1 2 3 4 5 6 7
| l = 0, r = n - 1;
mid = l + r >> 1; 对应 r = mid, l = mid + 1; mid = l + r + 1 >> 1; 对应 r = mid - 1, l = mid;
|
前缀和和差分
二维前缀和
1 2 3
| S[i, j] = 第i行j列格子左上部分所有元素的和 以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵的和为: S[x2, y2] - S[x1 - 1, y2] - S[x2, y1 - 1] + S[x1 - 1, y1 - 1]
|
二维差分
比较巧妙:
如果q是全0的,那么其差分数组也是全0的,但实际上,q[i] = 0 +
q[i]。(所以就相当于对一个元素的小区域实现了加c(即q[i])的操作)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| void insert(int x1, int y1, int x2, int y2, int c) { a[x1][y1] += c; a[x1][y2 + 1] -= c; a[x2 + 1][y1] -= c; a[x2 + 1][y2 + 1] += c; }
for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { cin >> q[i][j]; insert(i, j, i, j, q[i][j]); }
|
一般方法:
a是s的差分数组
1 2 3 4 5 6
| for (int i = 1; i <= n; i ++ ) for (int j = 1; j <= m; j ++ ) scanf("%d", &s[i][j]); for (int i = 1; i <= n; i ++ ) for (int j = 1; j <= m; j ++ ) a[i][j] = s[i][j] - s[i - 1][j] - s[i][j - 1] + s[i - 1][j - 1];
|
基本的位操作
看第k位是几
先移到最后一位:n >> k
(k是从0开始,比如100中,1是第2位)
看个位是几:n & 1
综合:n >> k & 1
lowbit(x),返回x的最后1的位置
1 2 3 4 5 6 7
| 实现:x&(~x+1) (~x为x取反)
lowbit(n) = n & -n
lowbit(1010)=10
lowbit(1001000) = 1000
|
数据结构
数组模拟链表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
int head, e[N], ne[N], idx;
void init() { head = -1; idx = 0; }
void add_to_head(int x) { e[idx] = x; ne[idx] = head; head = idx; idx++; }
void add(int k, int x) { e[idx] = x; ne[idx] = ne[k]; ne[k] = idx; idx++; }
void remove(int k) { ne[k] = ne[ne[k]]; }
for(int i = head; i != -1; i = ne[i]) cout << e[i] << ' ';
|
Trie树
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| const int N = 100010;
int son[N][26], cnt[N], idx; char str[N];
void insert(char str[]) { int p = 0; for(int i = 0; str[i]; i++) { int u = str[i] - 'a'; if(!son[p][u]) son[p][u] = ++idx; p = son[p][u]; } cnt[p]++; }
int query(char str[]) { int p = 0; for(int i = 0; str[i]; i++) { int u = str[i] - 'a'; if(!son[p][u]) return 0; p = son[p][u]; } return cnt[p]; }
|
并查集
主要工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| int p[N];
int find(int x) { if (p[x] != x) p[x] = find(p[x]); return p[x]; }
for (int i = 1; i <= n; i ++ ) p[i] = i;
p[find(a)] = find(b);
|
STL
vector
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| size();
empty();
clear();
A.push_back(t);
for(auto i = a.begin(); i != a.end(); i++) cout << *i << ' ';
for(auto& num : nums) cout << num << ' ';
sort(a.begin(), a.end());
vector<int> res(nums.size(), 0);
|
pair
可以存储一个二元组,前后数据类型可以不同
1 2 3 4 5 6
| pair<int, string> p;
p.first; p.second;
typedef pair<int, int> PII;
|
string
1 2 3 4 5 6 7 8 9
| size()/length(); empty();
string a = "yxc"; a += "def";
a.substr(1, 2);
|
queue
1 2 3 4 5 6 7 8 9 10
| push(); pop(); front(); back(); empty(); size();
queue <int> q; q = queue<int>();
|
priority_queue
优先队列
是用堆来实现的,默认是大根堆(大的在队头)
1 2 3 4 5 6 7 8
| push(); top(); pop();
priority_queue<int> heap;
priority_queue<int, vector<int>, greater<int>> heap;
|
stack
1 2 3 4 5
| size(); empty(); push(); top(); pop();
|
常用知识
取整
正数除以2是向下取整:5/2=2
负数是向0取整:-5/2=-2
将字符数字转换为int
1 2 3
| char a; int i; i = a - '0';
|
max函数是max(a, b);
万能头文件:#include<bits/stdc++.h>
i++
1 2 3 4
| a[4] = {1, 2, 3, 4}; int cnt = 0; cout << a[cnt++] << endl;
|
1 2 3 4 5
| a[4] = {1, 2, 3, 4}; int cnt = 0; a[cnt++] = 100; cout << a[0] << endl;
|
多个判断条件书写时
把可能越界的条件放在后面(这样就是后判断,可能不会判断就不会越界)
如lecctode
第27题 移除元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Solution { public: int removeElement(vector<int>& nums, int val) { int i = 0, j = nums.size() - 1; while(i <= j) { while(i <= j && nums[i] != val) i++; while(i <= j && nums[j] == val) j--; if(i < j) nums[i++] = nums[j--]; } return i; } };
|
整型最大最小量的使用
1 2 3 4 5
| #include<climits>
#include<limits.h>
INT_MAX, INT_MIN;
|
求最大公约数
1 2 3
| int gcd(int m, int n) { return n ? gcd(n, m % n) : m; }
|
求最小公倍数
判断质数
1 2 3 4 5 6 7 8 9
| bool is_prime(int x) { if (x < 2) return false; for (int i = 2; i <= x / i; i ++ ) if (x % i == 0) return false; return true; }
|
Devc++添加c++11
1 2 3 4
| int gcd(int a, int b) { return b ? gcd(b, a%b) : a; }
|
时间复杂度
C/C++一秒钟可以算 \(10^8\)次(可以由此判断会不会超时)