1-杂项
一些杂项Trick
区间合并
using pii = pair<int, int>;vector<pii> a, res;
sort(a.begin(), a.end());auto [st, ed] = a[0];for (int i = 1; i < a.size(); ++i) { auto [st1, ed1] = a[i]; if (st1 <= ed) { ed = max(ed, ed1); } else { res.push_back({st, ed}); st = st1; ed = ed1; }}res.push_back({st, ed});读题
取模
998244353和1e9 + 7都是质数
998244353适合用于做FFT和NTT变换
灵感
- 代码上串行,如果数据互相独立可视作并行
- 第k个都是实虚指针
- 移动隔板可看作合并空白区间
取整
通用
由于C++不是统一向下取整而是向0取整所以没什么用
离散加小步长
需要单调
向下取整和向上取整
向下取整是闭开
向上取整是开闭
和在整数域上由于向下取整和向上取整对应的区间中总是在同一直线,同时向下取整的左端点总是小于向上取整的左端点,向下取整的右端点总是大于向上取整的右端点,故两者在整数域上等效,同时
中点
中点m取n的时候,偶数n,m在偏右,如遍历左边取到m的话,奇偶都是左边偏大,取n - 1的时候,奇数左偏大,偶数左右相等
中点m由n时,
- 偶数n,m偏右中点,遍历左边取m的话,左偏大,不取的话,一样大。
- 奇数n,m不偏不倚,遍历左边取m的话,左偏大,不取的话,右偏大
取的话
左[l, m],右[m + 1, r]
不取的话
左[l, m - 1], 右[m, r]
中点m由n-1时
- 偶数n,m偏左中点,遍历左边取m的话,一样大,不取的话,右偏大
- 奇数n,m不偏不倚,遍历左边取m的话,左偏大,不取的话,右偏大
取的话
左[l, m],右[m + 1, r]
不取的话
左[l, m - 1],右[m, r]
和中点m由n时的取不取情况是镜像的,但是表达式只取决于左边取不取中点
能把映射到
循环
序列
主要运算对象,
| 左指针i | 右指针j | 区间长度l |
|---|---|---|
| 实 | 实 | j - i + 1 |
| 实 | 虚 | j - i |
| 虚 | 实 | j - i |
| 虚 | 虚 | j - i - 1 |
一般常用
do-while
即循环体至少执行一次。
场景 1:初始状态不合法,必须先动
快排。i = l-1 在数组外面,不能先判断 q[i],必须先 ++i。
场景 2:提取数字的每一位
// n = 0 时也要输出 "0",至少执行一次
do {
digits.push_back(n % 10);
n /= 10;
} while (n > 0);如果用 while (n > 0),n = 0 时一位都不会提取。
场景 3:输入校验 / 重试
do {
cin >> x;
} while (x < 1 || x > 100); // 至少读一次,不合法就重来场景 4:至少比较一次的迭代
// 找到下一个不同的元素
do { ++j; } while (j < n && a[j] == a[i]);总结
| while | do-while |
|---|---|
| 先判断,可能一次都不执行 | 先执行,至少跑一次 |
| 初始状态已合法 | 初始状态不合法 / 必须先动 |
配置环境
学校的破烂电脑扩展不更新的话Intelligence直接失效,没网的话要用Vscode只能用Code Runner
Tasks.json
必要的就type, label, command, args
tasks:[ { "type" : "cppbuild", "label" : "build", "command" : "g++", "args" : [ "-g", "${file}", "-o", "${workspaceFolder}/bin/${fileBaseNameNoExtension}.exe" ] }]性能相关
一些卡常的性能细节
IO
ios::sync_with_stdio(false);cin.tie(nullptr)开了后cin的性能追平scanf(),可以用cin.tie(nullptr)->sync_with_stdio(false)- endle要重新刷新缓冲区,性能不如
\n
数据编排
SOA在SIMD优化下比AOS会好一些
离散化
分两种,一种哈希,一种二分
哈希
哈希适合需要编码的数据
struct discretization { unordered_map<string, int> m;
discretization(const vector<string>& a) { for (int i = 0; i < a.size(); ++i) { m[a[i]] = i; } }
int operator[](string x) { return m[x]; }} dt;二分
二分适合数值大数量小的数据
struct discretization { vector<int> help;
discretization(const vector<int>& a) : help(a) { sort(help.begin(), help.end()); help.erase(unique(help.begin(), help.end())); }
int operator[](int x) { return ( lower_bound(help.begin(), help.end(), x) - help.begin() ); }}元素迁移到完全二叉树上
设完全二叉树元素数量为,要扩展到满二叉树,其中n为1-base的满足的最大层值,即
故,如果元素1-base的话那就是从上一层最后一个元素到该层的非最后一个元素
则 ,
假如是满足而不是,则有,即,1-base的话就是从该层第一个元素到该层最后一个元素。
则, 理论上来讲,需要开即大小的数组
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!