从题面来判断算法
HotDogSeller · · 算法·理论
我们经常会有这样的时候:
辛辛苦苦学了几年OI,等上了考场的时候却发现所有的题目根本看不出来有什么逻辑性,甚至觉得毫无算法性可言,但是等到考试结束看题解又会发现确实是要用到某些算法,还用的挺规整,经典!
于是乎你又在爆零的WA声中痛哭一夜......
所以,这篇文章就来教你根据题面来猜算法!
希望大家不要重蹈热狗贩子的覆辙......
注意:本文中讨论的都是普及组和提高组算法,很简单,因为省选及以上的作者没学过(悲),但他们至少可以管饱你的CSP-J和CSP-S。
1 出现关于取模的语句
当题目中出现诸如 “将答案对998244353取模” 时的类似语句时,一般不可能是暴力,因为这种答案一般要你输出诸如方案数的答案。
例如洛谷P1077,是让你输出可以一共有多少种摆花的方案。由于已知答案要取模,所以答案取模之前一定数值较大,所以不可能是对所有的摆花方案一一枚举。 而实际上,这一题是个DP。
当然有的时候不一定有取模就是DP,这题也可能是数论。因为 有的时候一些答案不考虑特殊情况,是可以用数学公式算出来的。 ABC 262-E就是一个经典的例子,这里面的红点可以放在哪些地方是可以推导出来的,不需要DP,只需要公式。
这道题当时完全蒙骗了我 ,我居然还傻傻的在告诉别人这道题DP的正确性。
2 最大值最小,最小值最大或出现单调性
二分。
它是裸的!
比如?这题!
注意这题的措辞:
最短跳跃距离尽可能长?
这题二分!二分跳跃距离!
还有一种不那么裸的题型,大致是这个样子:
输入m,求
然后还贴心地给了你
这题看似是个数学题,其实也可以用二分,因为我们看到,函数
(当然:如果你数学学得好,还可以用这种方法同时解出这个方程的另一个解!)
3出现区间统一查询
这样的题面一般也是针对暴力来下套的,毒瘤一点的每一次操作针对全体元素,于是乎你喜提TLE,那么,接下来的指南会对你有所帮助。
数据完全静态,没有修改
那么此时,你需要前缀和或后缀和,当然,ST表也是一个不错的选择。尤其是当出现
数据为动态,有修改
一般情况下,有三种算法可供考虑:线段树,树状数组和根号分治。
线段树和树状数组的时间复杂度都是
至于线段树和树状数组的选择。线段树在区间修改的题目中优势更大,并且原理 个人 认为较为简单易懂;而树状数组的优势在于其占据的空间更小,并且 涉及每一次的单点修改时,线段树的复杂度是严格的这意味着线段树还可以卡常。
4 数据范围很小,但是暴力又会unaccepted
例题:洛谷P1433
乍一眼一看,这一题
但我告诉你:
此时, 状压就成为了首选!
当然,还有的时候,如果数据是很小,小到只是二位数,但是数据达到不适用状压的条件时,那么你也可以尝试折半查找。
5 数据的答案具有单一性或规律性
此时不要犹豫,AC就在打表里等着你!
什么叫单一性?举个简单的例子,考虑如下的问题:
输入k,输出第k小的质数。
这种问题输出的永远是同一种类型的答案,没有变化。因此,可以直接自行本机打表,做出包含所有质数的向量,到时直接输出即可。
还有一种打表,是根据数据的变化而变化的,我们更多称之为 预处理。像是ABC 258-E,我们在接收到数据后预处理每一袋土豆会有多少个,由于这题数据是有规律的,所以我们不需要无限的打表,只要找出规律再进行取余查找即可。
6 出现操作对象之间的两两关系时
例题:ABC 190-E
这一题乍一眼一看,似乎是关于如何生成一个合法的序列的,但是你这么想。
把宝石看成节点,可相邻关系转化成边,那么这就是一个图上找路径的问题!
因此,我们得出结论,这种题目 一般都是图论!
7 有些题目看似可以贪心,但是会被会被Hack掉
这种题目基本都是DP或者反悔贪心
8 呈现出指数级的规律
举个例子,找规律输出正方形。
当n=1时,输出:
+-+
| |
+-+
当n=2时,输出:
+-+-+-+
| | | |
+-+ +-+
| |
+-+ +-+
| | | |
+-+-+-+
当n=3时,输出:
+-+-+-+-+-+-+-+
| | | | | | | |
+-+ +-+ +-+ +-+
| | | |
+-+ +-+ +-+ +-+
| | | | | | | |
+-+-+-+ +-+-+-+
| |
+-+-+-+ +-+-+-+
| | | | | | | |
+-+ +-+ +-+ +-+
| | | |
+-+ +-+ +-+ +-+
| | | | | | | |
+-+-+-+-+-+-+-+
很显然,第
9 查询关于连通分量的数据
并查集!你需要它!
不记得是CF上的哪一题了,大意是有一个长度为
注意题面,我们可以将它理解为
10 序列中元素的数值较小
大多数时候,序列中的数值一般都是 小于等于
总结
有的时候,某些题目标算并没有那么遥不可及,只不过是题面吓吓你罢了。在写题的时候要记住,编程算法的本质就是一种优化手段,因此,在遇见复杂度过大的步骤时,便可以考虑算法优化。