OI程序常见的设计陷阱

Posted linearode

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OI程序常见的设计陷阱相关的知识,希望对你有一定的参考价值。

不要偷懒

有时候为了方便,我会大量使用宏定义。但是最近我发现下面这两个宏定义老是出问题:

1 #define SET(x,a) memset(x,a,sizeof(x))
2 inline void work(){
3     SET(head,0),SET(vis,0),SET(dis,0x3f);
4     //do something
5 }

这个宏定义似乎在初始化的时候会莫名奇妙地出现一些问题。

另外,还有这个:

1 #define RP(i,a,b) for(register int i=a; i<=b; i++)
2 inline void work(){
3     vector<int> ver;
4     //do something
5     RP(i,0,ver.size()-1){
6         //do something
7     }
8 }

当你定义了一个 RP 的循环宏时,它的判断会出一些问题。比如说在上面这个例子,如果ver.size()==0,那么正常的for就不会进入这个循环。但是宏定义之后它的判断顺序似乎发生了改变。

很奇怪吧?因此,有些宏还是不要乱用。我之后也要注意这个问题。

不要乱卡常

网上有一些奇奇怪怪的卡常方式,比如说把i++写成i=-~i,或者用大量的逗号链接若干个语句。对于前者,这个二进制优化其实并不如想象中的那么出色,对速度的提升不明显。(虽然我本人也喜欢把i++写成++i以提高速度)对于后者,虽然逗号运算符在一定程度上可以提高效率,但有些时候会出现一些奇怪的问题。我记得很久以前,我喜欢把很多语句用若干个逗号连成一条;但是有时候,程序可能只会其中的部分几条,剩下的会被忽略!我不知道是否真的有这个问题,但是我的建议还是不要乱用逗号。

注意空间复杂度

在学习任何一个算法或数据结构时,一定要翔实记录它的空间复杂度。比如说,trie树的空间复杂度是多少?一般要开多大?用链式前向星存无向图,是否把边数组开成题给的两倍?这些问题不注意,你也许可以通过样例,但最后可能一分都拿不到。如果你是在网上评测,有时候评测机并不会反馈RE的信息,而是WA。如果不加注意,你会因为这个问题而调试很久。

注意类型转换

始终注意类型转换。有时候即便你把所有的数值变量开成long long类型,你可能会在赋值的时候忘记把一个int类型的表达式进行转换。这样,表达式在被赋值前就会发生溢出。任何时候要牢记各种变量的类型,并时不时转换一下。

另外,强制转换的速度会相当慢。如果你想转换成long long类型,直接在变量前乘上1ll;对于普通double类型,可以直接乘上1.0;对于更特殊的long double或是__int128类型,你就只能强制转换了。

以上是关于OI程序常见的设计陷阱的主要内容,如果未能解决你的问题,请参考以下文章

IoT创业:硬件创业,你应避免的 5 个常见陷阱

Linux共享内存使用常见陷阱与分析

OI实用工具 持续更新ing

想要落地微服务架构,这些设计的陷阱你了解吗

Python 进阶指南(编程轻松进阶):八常见的 Python 陷阱

股市是上帝根据人性的弱点而设计的一个陷阱