(二)基本算法
二分
一种比较通用二分写法,不太用考虑边界的问题。
int l = st, r = ed, ans = ed + 1;
while (l <= r)
{
int mid = (l + r) >> 1;
if (check(mid)) ans = mid, l = mid + 1;
else r = mid - 1;
}
if (ans == ed + 1) printf("No Solution!");
else printf("%d", ans);
正确性分析:
每次 与 必有一个变化,因此不会陷入死循环。
始终保存的是满足条件的 ,所以答案永远是当前情况下的最优解。
一个小 :二分调题时,将错误的 单独拎出来检查是比较好的。
例 :[NOIP2001 提高组] 一元三次方程求解 - 洛谷
考虑三次函数的曲线形式,找到在 轴两侧的点,二分答案即可。
例 :寻找段落 - 洛谷
通过二分答案,转化为判定性问题。
欲判定当前平均值 是否可能可行:即是否有
考虑将 全部减去 ,做一遍前缀和。对于当前 , 的最大值是最优的情况,于是上单调队列即可。
二分答案,判定可行性:在 次操作内是否能使每段距离都大于 。
直接遍历即可,每次遇到 的距离,就对它进行操作直到它 为止。
陷入的一个误区:
二分判定可行性的时候,误以为需要找到最优方案,来判断是否能使当前理想解成立。
于是想尽办法构造了最优方案,其实完全没有必要,每一次只用贪心地去除任何能导致当前解不成立的情况即可。
评测记录 - 洛谷(仅供参考,代码构造了最优判定方案,常数较大,不够优秀)
例 :进击的奶牛 - 洛谷
类似于例 。
例 :刺杀大使 - 洛谷
比较板,二分 判定。
考虑 的单调性:随 增大而单调递减。
将 看做函数,考虑二分的数学意义,类似于求二次方程的解,找到最接近于 的解即可。
考虑如何快速求解 ,发现记录前缀和即可。
时间复杂度
发现订单的满足二分条件,二分需要修改的订单即可。
非常显然的一道二分,刷题数明显随答案增大而减小。但是我非常脑抽的把二分 上界设成了 ,调了很久才过。
要注意的一点是,这道题更新边界的条件是 ,而更新答案的条件是 。
例 : [HEOI2016/TJOI2016]排序 - 洛谷
收获:当二分的单调性不显然甚至感觉上错误的时候,不妨先想想 函数的写法。
毕竟二分的单调性也依托于 函数而存在,根据 函数来判定单调性是否正确。
我的理解:二分通过你设计的 函数(返回 )来使得 单调不递减。
详细一点地解法见 NOIP复习(三)线段树 的 例 。
CDQ 分治
思想:处理点对统计问题时,将序列分为两半。考虑到点对 可以分为三类:, 。上两类可以递归进入两侧序列分治处理,对于第三类单独设计算法进行处理。
分治的一个例子就是归并排序。
首先将点对去重,以 为关键字排序。 分治,每次考虑左区间对于右区间的贡献,将左,右区间分别以 为关键字排序,双指针扫描,用树状数组维护贡献即可。
将询问转化为二维前缀和,离线 分治。每个询问变为 个点,标记权值为 ,全部与输入数据一同扔进一个序列里面。 分治即可。
添加一维时间,将问题看做统计满足条件的三元组 个数即可。
构造题
TASK1:前缀和数列构成 意义下的一个剩余系。
首先发现 必须在首位。思考构造,可以有
有解的判定,发现 为奇数的时候,无法构造满足条件的序列, 个数的和被 整除。
TASK2:前缀积数列构成 意义下的一个完全剩余系。
发现 必须在末位, 必须在首位,若 显然无解。
构造 ,即
证明 互不相同:证明从略,考虑威尔逊定理的证明过程易知。
猜一手结论,最大的 个数一定可以被取到。
令小于最大值的为 , 大于最大值的为 。画一个折线图,发现取最大值所在点为起点的时候满足条件。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】