技巧

通用

观察题目的给的问题,有什么形式,怎么思考方便,按什么顺序?

不要闲着,随便想点什么。

把题目分成若干个部分。

随时贪心,考虑舍弃掉一定不会更优的方案。考虑舍弃一定不会造成贡献的元素。

手玩。

坚定信念,一定能做。

把你的问题用数学的方式表示出来,随便转化转化。

把已经会的东西,等待探究的问题,可能的思路都写下来,防止自己胡思乱想。

正难则反。

转化成经典问题,或者考虑这个东西是不是比经典问题强,或者比经典问题多什么性质。

对于一个困难的过程,我们可以尝试进行等价转换。

把问题放到二维平面上,进行一些初步转化,往往能把看起来很复杂的问题简单化(JOISC 的很多题)。

寻找组合意义。

考虑 flow,hash 等奇怪的东西。

增量,调整,分治,合并,贪心,枚举,DP。

数据结构

把当前转化出来的问题重新写一下,想一想有没有漏掉什么性质。

离线。可持久化。

考虑修改对询问的影响。

性质。

注意空间。

更换顺序。

均摊。

能不能根号分治?

对于一类东西,我们可以把判定性问题转化成一个查询问题,通常是查询最小/大值。比方说判定是否所有数都 \(<x\),可以转为查询最大值,判定是否 \(<x\)

任意转存在。如果说要求对于范围内每个元素都要满足一些性质,求这样的范围个数,我们可以找出不满足性质的元素,把包含这个元素的范围干掉,然后求没有被干掉的区间。

不包含一个点/子树的某些最优化问题,往往可以找出全局最优解,然后发现可能答案不一样的,只有一些链,在这些链上做是快的。

各种离线分治算法。

DP

比方说 1D1D 转移,我们既可以枚举上一个结束的位置,也可以考虑要不要把当前位置加入。这种想法还有一些别的应用。

比方说树上有若干个不同的关键点,要你选出若干条以它们开头的链,满足这些链不交,且总长最长。你当然可以记录一个表示当前子树内从根开始最长的没有被覆盖的链的长度,你也可以记录 0/1/2 表示这个子树结束了/有一条从根到某个关键点的链/有一条从根到某个非关键点的链。

总而言之,把原本一次就找出来的东西分成若干次增量构造,可以省下时间。

关于优化,常见的就不说了。还有一些,我们可以考虑对值域和数域互换。比方说,求互异分拆数的 \(O(n\sqrt{n})\) 算法,就是发现最多 \(\sqrt{n}\) 个数,然后你把行列交换一下,用完全背包去做 \(\ge x\) 的有多少个。

还有一些,可以 cdq 分治,这不局限于偏序的转移,凡是直接转移复杂度过高,但是可以打包的,都可以这么做。

交换值域与定义域。

对于值域特别大但是很难做到时间复杂度与值域无关的,考虑猜测答案是多项式,然后插值。

数学

\[\sum_{d\mid n}\mu(d)=[n=1]\\ \sum_{d\mid n}\varphi(d)=n\\ \sum_{i=0}^n(-1)^{i}\binom ni=[n=0]\\ \sum_{i=1}^{+\infty} [n\ge i]=n \]

对于树,点数 - 边数 = 1。对于树上连通块 \(S\)\(u\in S,fa_u\not\in S\) 恰好有一个。

对于两类组合对象,让你对合法的某一类计数,其中这类合法跟另一类有关,但是不好直接做,我们可以构造双射。比如问能被某些操作清空的序列有多少个,我们可以规范化操作方式,使它们一一对应,然后统计操作方式。

寻找组合意义。例如对于一类计数问题,我们可以考虑恰当地构造一些权值,然后更换计数角度进行计数。

对于无穷情况,我们考虑有贡献的部分。比方说,虽然枚举 \(S\) 后中间可能有非常多次在 \(S\) 外的部分,但我们可以算一下下一次出现某一个数的概率,然后直接算。例如 [AGC038 E] Gachapon。

构造

手玩一玩,多试几个,找找通用的办法,找找规律,看看性质。

什么时候无解?

如果有解,有多少?什么形式?有没有一种好看的?能不能统一转化成一种好看的?

有没有一类情况是容易的?能不能把别的也转化过来?

用它给的操作构造出若干种比较方便的“基本操作”。

图论

dfs/bfs 生成树。

杂项

对于树上把叶子匹配的问题,可以考虑分成 dfs 序的前一半和后一半一一对应。更常用的思路是考虑重心为根。

树上判定是否是一个连通块,除了 点-边=1 以外,还可以考虑数根的个数,具体来说,数那些 \(u\in S,fa_u\not\in S\) 的,当然,这里需要额外钦定根的父亲是 \(0\)

常见解题思路

思想:分治,去除无用状态,合并重复状态,预处理,枚举,贪心,交换枚举顺序,直接考虑答案的性质,调整。

概率期望:dp,消元,minmax 容斥,转成计数。

dp:

dp 优化:数据结构,决策单调性,斜率优化,优化状态,拆贡献(常见方法有差分前缀和之类的),卷积。

树上问题:点分治边分治链分治,重剖长剖,dsu on tree,树上各种序(dfs 序,欧拉序,括号序)。动态树(LCT,ETT)。

序列:差分,前缀和,划分成若干段(单调段,连续段)。

区间:分治,扫描线,合并,

条件转化:观察题目中的性质,哪些东西是已知好做的;找到必要条件,看看是不是充要的。

最优化:考虑弱化我们考虑的元素,只需要保证考虑的元素集合里面有最优解就行了;考虑把每个元素强化,只要不超过最优解就行了;考虑把最优解的形式统一成一个最好看的;考虑排除一定不优的元素。

计数:排列组合,容斥,反演,构造映射(不一定双射),交换求和顺序。组合数拆成阶乘或者较小的两项。考虑计数的组合意义,考虑配凑一些容斥系数。

数据结构:离线!!!!!!!!!!可持久化,转换维度,找代表元素,转换为数点,考虑修改对询问影响,数据结构嵌套。根号算法,分治,考虑真正有贡献的部分。

字符串:贡献的转化,特殊字符拼接,枚举长度,

非常见算法:hash,随机,矩阵,流。

posted @ 2024-01-24 17:07  PYD1  阅读(18)  评论(0)    收藏  举报