解题思路总结

拆点

因为处理点往往很困难,且图论中大部分算法是对边进行操作,故可以将点拆成两个状态并连边,再运用算法解决问题。

常用于:网络流建立模型、布尔值相关问题

例题:
【SCOI2007】蜥蜴

树上序列

大部分树上序列(如欧拉序)都让同一子树的节点连续排列,从而使诸如线段树、莫队等的数据结构和算法可以解决树上的在线查询和修改的问题。

比如树上莫队和树链剖分,其实都用到了类似的思想,从而减小了时间复杂度,故而这是解决树问题的一个非常强大的工具。

例题:
【WC2013】糖果公园(详解)

异或的特点

a a a 异或上数 b b b 得到数 c c c ,则必有 c ≥ a 、 c ≥ b c ≥ a 、c ≥ b cacb ,这是有时解决异或题目非常有用的性质,比如博弈论中经典的 N i m Nim Nim游戏的解法证明正是基于异或的这个性质。

例题:
博弈论—— N i m Nim Nim游戏

影响的传递

在处理数组时,有时会遇到区间处理的问题,如果这个问题无法快速合并和转移(即无法使用线段树、莫队等类似算法时),那么可以考虑数与多个数之间的影响,考虑能否进行分块并快速求出分出的每一块的贡献,进而将问题简化。

例题:
【NOIP2018 提高组】 铺设道路

倍增法

在处理区间上的问题时,若两个相邻区间间存在比较容易的合并方法,则可以使用倍增法将时间复杂度中的一个 n n n 降为一个 $㏒2n $。

倍增法的运用非常多,如: R M Q RMQ RMQ问题中的st表、求 L C A LCA LCA中的倍增法后缀数组 S A SA SA的快速求解……

例题:
【模板】后缀排序

贡献

传递性

有些时候贡献的传递性非常重要,它可以帮助你降低时间复杂度,比如从 O ( n ) O(n) O(n) 降到 O ( log ⁡ 2 n ) O(\log_2n) O(log2n) ,这一方法在 S O S D P SOS DP SOSDP 中有所使用。

计算技巧

在整体贡献难以计算时,我们可以考虑差分,也可以考虑将贡献的式子列出来后,分开统计便于计算的部分,最后再合在一起处理。区间历史和的统计就是利用了类似的想法。

例题:
CF1427G One Billion Shades of Grey

答案的区间性

当一道题的暴力非常好写时,可以先从暴力算法入手,然后考虑优化,其中一个优化的方法就是考虑答案之间是否存在区间性,即一个答案它和满足某些条件的答案是否有一定的条件关系(比如 当 i > j i>j i>j时,必有 a n s [ i ] ≥ a n s [ j ] ans[i]≥ans[j] ans[i]ans[j] ),从而降低时间复杂度。

这一思想在莫队中有所使用,区间的转移其实就是这样的,还有求了后缀数组 S A SA SA 后求 h e i g h t height height 数组、manacher算法求解最长回文子串,也是运用了同样的方法。

例题:
【NOI2015】品酒大会

归纳法证贪心

当某一个贪心做法没有得到证明时,可以单独拆分出两个相邻节点并进行最优性判断,通过交换操作的先后顺序得到不同的答案,再根据这个答案判断操作的先后顺序,根据这个答案得到的结论可以运用数学归纳法推广到整体,依据结论排序后得到的操作顺序即是最优解的操作顺序。

例题:
皇后游戏
[yLOI2019] 梅深不见冬

二分答案

二分这一方法可以有效地降 O ( n ) O(n) O(n) 降为 O ( log ⁡ n ) O(\log n) O(logn) ,但前提是二分的对象具有单调性,因此在进行二分前需要先证明单调性(单调不减或者单调不降),并根据题目要求和单调性调整 l l l r r r 的值。比较常见和易理解的写法形如:

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

当然,该写法也可以进行适当的变形,具体情况具体分析。

而要对答案进行二分,首先要证明答案对某一限制具有单调性,其次验证答案的复杂度不能过高。依本人拙见,二分答案其实就是套了个二分的模拟(但是模拟题真的好难写啊!!!!!!),因此在判断答案合法时的代码尤为关键。

例题:
[SHOI2015] 自动刷题机
[NOIP2011 提高组] 聪明的质监员

玄学做题技巧

数据范围小时

可以从两个方面思考:多维 d p dp dp 和暴力求解。而当你经过一番推导之后,发现该题几乎没有好的性质的时候,可以选择直接打暴力——当然,在打完暴力还有时间的情况下,可以去试着证明一下时间复杂度,也许会惊奇地发现看似绝对爆的时间复杂度其实并不会爆。

例题:
卜卦
Tax

数学相关题目

可以先推式子,推不出来后打暴力,然后通过分析答案性质来反向推出答案的一些规律。

例题:
Koishi Loves Construction

一些可合并的影响传递技巧

若需要维护区间内一些数据的值且值与值之前可能会有贡献,可以考虑使用矩阵维护值,从而使用线段树维护。

例题:
2025 – 苍穹计划 – NOI排位赛 #13 B

一些暴力技巧

在写暴力时,如果需要动态加入元素+查询该元素是否出现过,可以考虑 s e t set set 或者 m a p map map,而不是手写一些东西,费时且容易出错。

例题:
[SDOI2016] 墙上的句子

分治技巧

常见分治为二分,像快速幂、归并排序之类的算法都是用到了分治思想。而在进行分治的时候,最重要的是如何快速地将区间答案合并,我们可以通过排序(比如CDQ分治)或者剪枝来优化时间复杂度。

例题:
平面最近点对(加强加强版)
【模板】快速幂
[Violet] 天使玩偶/SJY摆棋子

DP

状态设计时的一些技巧

当需要求的东西有一些奇奇怪怪的式子时,可以考虑将该式子转化成一些常见的求解内容,比如方案计数。

例题:
[ARC124E] Pass to Next

数位DP

转移时的一些小技巧

转移时,可以通过枚举状态然后判断是否合法来转移,这样写起来更清晰,而且因为数位dp往往转移复杂度不高,可以接受这样的枚举。

例题:
[TJOI2019] 甲苯先生的线段树
[SDOI2016] 储能表

也可以考虑递归地转移,从答案状态往边界状态找。

例题:
[CQOI2016] 手机号码

网络流

一些优化技巧

当点和边的范围过大时,可以考虑这张图的性质(比如二分图中,左右两边是否有一边的点数很小),模拟网络流求解答案。

例题:
[Ynoi Easy Round 2018] 星野瑠美衣

一些建图技巧

  1. 当无脑建图复杂度过高时,可以考虑能否利用网络流的一些性质来让一些路合并在一起,跑贡献的方式类似于差分(这在跑费用流的时候是好理解的)。

    例题:
    [SNOI2019] 通信

  2. 当题目限制“一对一”的时候,可以考虑差分的形式把“一对一”变成“一对多”。

    例题:
    P2570 [ZJOI2010] 贪吃的老鼠

  3. 当题目需要在一个确定的条件下最小化另一个值时,可以考虑费用流,而费用流有两种做法:

  • 传统费用流做法,将确定的条件化为流量,跑最小费用最大流。

  • 利用最小费用最大流的性质,跑满足某些条件的最小费用可行流,即利用费用为负无穷来实现先跑这条边再跑其它边(注意和上下界网络流区分:下界是必须跑的,而这个做法是尽量跑的)。

    例题:
    CF2046D For the Emperor!

  1. 在建图时,若点存在多个状态且不同状态有不同的连边时,可以考虑把点拆成多个点,即从一维点升为二维点,从而更方便的维护某些东西。

    例题:
    [NOI2012] 美食节

  2. 在建图时,要利用好割掉这条边等价于某个选择(比如在二选一的情景中)这一关键信息,从而最小化某些值。

    例题:
    [ABC397G] Maximize Distance

    [ARC142E] Pairing Wizards

  3. 在处理一些对区间进行要求的限制时,若数据范围不大,可以考虑求出每个点对应的区间,然后由这个点向符合条件的区间内的点连边。

    例题:
    [AGC031E] Snuke the Phantom Thief

对偶图

在做图论题目的时候,有时候可以利用对偶图的一些性质来解决问题,比如:沿着边可以从左上到右下等价于格子从右上到左下是不联通的(可以把沿着边走想象成把两个格子分开)。

例题:
Express Eviction

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值