一些常用技巧的板子和 注意点mark

struct 封装多元组(类似 pair<>、tuple<>)

注意:重载运算符中的大小关系与实际比较意义相反,即 x.first > y.first 表示以维度 first 从小到大排序,x.first < y.first 则表示以维度 first 总是得到当前最大值。

struct T
{
int first, second, third;
friend bool operator <(T x, T y)
{
return x.first > y.first;
}
};
priority_queue< T >q;

二分

二分模板一共有两个,分别适用于不同情况。
算法思路:假设目标值在闭区间[l, r]中, 每次将区间长度缩小一半,当l = r时,我们就找到了目标值。

case1:找到满足 check() 的区间的左边界,形如 ..........voooooo(. 表示false,o 表示 true,v 表示目标值)

当我们将区间[l, r]划分成[l, mid][mid + 1, r]时,其更新操作是r = mid或者l = mid + 1;,计算mid时不需要加1。

int bsearch(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}

case2:找到满足 check() 的区间的右边界,形如 oooooov..........

当我们将区间[l, r]划分成[l, mid - 1][mid, r]时,其更新操作是r = mid - 1或者l = mid;,此时为了防止死循环,计算mid时需要加1。

int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}

实数上的二分

l = 0, r = n + 1;
double eps = 1e-6;
while (l + eps < r)
{
double mid = (l + r) / 2;
if (check(mid)) r = mid;
else l = mid;
}
return l;

建图去重边

#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
struct edge
{
int yo, w, next;
}e[M];
int top, h[N];
int n, m;
map<PII, bool> mp;
int main()
{
cin >> n >> m;
for(int i = 1; i <= m; i ++)
{
int x, y;
cin >> x >> y;
if (mp.count({x, y})) continue;
add(x, y);
mp[{x, y}] = true;
}
return 0;
}

离散化

lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

inline void discrete()
{
for (re i = 1; i <= n; i ++) b[i] = a[i];
sort(b + 1, b + n + 1);
int cnt = unique(b + 1, b + n + 1) - b - 1;
for (re i = 1; i <= n; i ++)
a[i] = lower_bound(b + 1, b + cnt + 1, a[i]) - b;
}

mark 遍历的不同顺序对程序时效的影响

P3355 骑士共存问题

做这道题时发现的玄学优化方法?

  • 若用 vector 存图应从右下角开始顺时针遍历;(不存图也要用这种方式)

  • 若用 链式前向星 存图应从左上角开始顺时针遍历;

取模运算 mod 相关结论

  • pxxmodp=0

  • p<xxmodp<x2

第一个结论显然,主要是证明第二个结论

p<x,令 xmodp=b

所以 存在 k,kN+,使得 x=kp+b

因为 p>b,则 kp+b>2b,即 x>2bx2>b

所以 xmodp=b<x2

gcd(a, b) 及其相关结论

欧几里得算法求两数的最大公约数,复杂度为 O(log(a+b))

c++ 也有内置函数 __gcd(a,b)

int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}

有结论

  • lcm(x,y)gcd(x,y)=xy

可用于 P8207 [THUPC2022 初赛] 最小公倍树 优化建图的转化

  • gcd(a1,a2,a3,...,an)=gcd(a1,a2a1,a3a2,...,anan1)

运用 P10463 Interval GCD,通过差分将区修 + 区间 gcd 转化为 点修 + 区间 gcd,而 gcd 刚好也满足差分转换

这里也给出以下简单的证明,新学到的方法,若想证明 A = B,可以分别证明 A ≥ B, B ≥ A

  • 证明:右部 ≥ 左部
    gcd(a1,a2,a3,...,an)=d
    a1d,a2dZ,不妨设为 a1d=k1,a2d=k2(k1,k2Z)
    因为 k2k1Z
    a2a1dZ
    其余可推广同理
    所以左部的最大公约数 d 至少是右部的公约数,满足不等关系

  • 证明:左部 ≥ 右部
    gcd(a1,a2a1,a3a2,...,anan1)=d
    a1d,a2a1dZ,不妨设为 a1d=k1,a2a1d=k2(k1,k2Z)
    因为 k1+k2Z
    a2dZ
    其余可推广同理
    所以右部的最大公约数 d 至少是左部的公约数,满足不等关系

取整与四舍五入

ceil((double)a / b) 向上取整,等价于 公式 x = (a-1)/b+1, 变形一下得 x = (a+b-1)/b

floor((double)a / b) 向下取整

round((double)a / b) 四舍五入(对小数只保留到整数位),若要保留小数位,假设保留 2 位,则 printf("%.2lf\n", round((double)x * 100) / 100);

快速幂

快速求解幂运算 ab ,时间复杂度为 O(logb)

利用二进制拆分的思想和倍增,如 313=3(1101)2=383631

在拆分的同时,对底数进行平方倍增

inline int quickpow(int a, int b)
{
int res = 1;
while (b)
{
if(b & 1) res = res * a;
a = a * a;
b = b >> 1;
}
return res;
}

mark 含减法的取模运算

一定要加上模数再取模!!! (number % mod + mod) % mod

快读快写

数据流比较大时用,这里只能用于整型输入输出

有时候输出可能会甚至爆 unsigned long long,其实也就只是 long long 的两倍,

此时可以用 __int128,范围顾名思义,NOI Linux 2.0 已经支持!!!但是要手写输入输出

inline int read()
{
int x = 0, f = 1; char c = getchar();
while(c < '0' || c > '9')
{ if (c == '-') f = -1; c = getchar(); }
while(c >= '0' && c <= '9')
{ x = (x << 3) + (x << 1) + c - '0'; c = getchar(); } // x = x * 10 + c -'0'
return x * f;
}
inline void print(int x)
{
if (x < 0) putchar('-'), x = -x;
if (x > 9) print(x / 10);
putchar(x % 10 + '0');
}

mark 多组不定数据输入单行字符串

形如

abcde
fghijk
lmnopq

可以用 while (~scanf("%s", c + 1))注意不要在里边加 &

其他

油猴 https://www.tampermonkey.net/

cf 翻译 https://greasyfork.org/zh-CN/scripts/465777-codeforces-better

at 翻译 https://greasyfork.org/zh-CN/scripts/471106-atcoder-better

CF-Predictor https://www.crx4chrome.com/crx/46813/

数学小工具 https://zh.numberempire.com/

外国论文 https://cp-algorithms.com/index.html

posted @   Zhang_Wenjie  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示