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程序常见的设计陷阱的主要内容,如果未能解决你的问题,请参考以下文章