目录

信竞学习笔记:算法复习

发表于
更新于
2 1.5~2.0 分钟 688

注:这是本人的课堂笔记。

本文主要介绍一些算法在提高级中的应用。

前缀和与差分

前缀和用于在 O(1) 的时间复杂度内求区间和,要求数组不变;差分用于在 O(1) 的时间复杂度内修改区间。

前缀和与差分是互逆的操作。

前缀和与差分可以和一些数据结构(如线段树、树状数组)相结合,实现更便捷的操作。

模板题:P2367

快速幂

快速幂可以快速求 a^b \bmod p 的值。其原理基于二进制。其核心思想是:指数 b 可以拆分成若干个 2^k 之和,采用分治算法实现。核心代码:

int qpow(int a, int b, int p) {
    int res = 1;
    while (b) {
        if (b & 1) res = (long long)res * a % p;
        a = (long long)a * a % p;
        b >>= 1;
    }
    return res;
}

模板题:P1226

离散化

离散化用于处理大数之间的相对大小关系,而不关心它们具体的值。通常来说,离散化题目的数据范围普遍较大(如 10^92^31),但数据量较小(如 10^5 \sim 10^6)。其主要通过排序和二分实现。

模板题:B3694

堆/优先队列

堆能够实现如下功能:

  1. x 加入到序列中;
  2. 输出序列中的最大/小值;
  3. 弹出序列中的最大/小值。

功能 1、3 的时间复杂度为 O(\log n),功能 2 的时间复杂度为 O(1)

STL 提供了一种数据结构——优先队列,底层是堆。定义优先队列如下:

priority_queue<int> q1; // 大根堆
priority_queue<int, vector<int>, greater<int> > q2; // 小根堆
priority_queue<int, vector<int>, less<int> > q3; // 大根堆

大根堆的堆顶是序列中的最大值;小根堆的堆顶是序列中的最小值。

优先队列支持如下操作:

q.top() // 取堆顶
q.pop() // 弹出堆顶
q.push(x) // 压入元素
q.empty() // 堆是否为空
q.size() // 堆的大小

模板题:P3378

STL map 容器

map 属于关联式容器,内容是键值对,底层为红黑树。定义如下:

map<key, T> mp;

其中 key 是键的类型,T 是值的类型。

map 支持如下方法:

mp[x] // 下标查询/插入
mp.insert(make_pair(x, y)) // insert 插入 pair 类型
mp.erase(key) // 根据键删除元素
mp.erase(pos) // 根据迭代器删除元素
mp.find(key) // 访问元素,若无返回 mp.end(),否则返回元素迭代器
mp.empty() // 容器是否为空
mp.size() // 容器大小
mp.clear() // 清空容器

双指针

双指针是一种优化技巧,核心思想是在序列上维护两个可以移动的指针,通过指针之间的范围控制并寻找答案。

例题:P1638