基础算法
快排调用
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\)次(可以由此判断会不会超时)