欢迎来到奇葩栖息地!欢迎加入Discord服务器:XfrfHCzfbW欢迎加入QQ频道:r01m9y3iz6请先至特殊:参数设置验证邮箱后再进行编辑。特殊:参数设置挑选自己想要使用的小工具!不会编辑?请至这里学习Wikitext语法。

120th Anniversary Origin.jpg共襄双甲子!热烈庆祝江苏省淮阴中学建校120周年!Logo of Huaiyin High School.png

那年那日的智障错误

From 奇葩栖息地

众所周知,编译器是没有脑子的⑨,所以在编写代码的过程中,总会有一些智障错误被编译器放过去,然后苦逼的OIer和程序员就要进行漫长的debug过程。

丧心病狂的出题人如果给了一个非常水的样例,你甚至不会发现自己的代码有问题,如果你没有进行对拍的情况下,这道题在ACM/CodeForces赛制比赛中就会显示WA、TLE、RE、MLE甚至是CE(并受到罚时),在OI赛制比赛中就会挂分/爆零论对拍的重要性

下面将举几个典型的智障错误例子。这些错误大部分都是crz和hsy践行过的

前置知识

在阅读下面内容前,你需要先知道这些东西:

关于评测状态:

  1. AC:Accept,程序通过。(绿)
  2. WA:Wrong Answer,答案错误。(红)
  3. CE:Compile Error,编译错误。(浅黄)
  4. PE:Presentation Error,输出格式错误UVa,说的就是你。(深黄)
  5. RE:Runtime Error,运行时错误。(紫)
  6. TLE:Time Limit Exceeded,超出时间限制。(黑)
  7. MLE:Memory Limit Exceeded,超出内存限制。(黑)
  8. UKE:Unknown Error,出现未知错误。(黑)

一些接下来代码中可能会出现的宏定义/常量:

#define rg register
#define ll long long
#define ull unsigned long long
const int intinf=0x7f7f7f7f;
const ll llinf=0x7f7f7f7f7f7f7f7f;
const double dbinf=2e18;
const double alpha=0.72;
const double delta=0.97;
const double pi=acos(-1)

会CE

  1. struct edge{
    	int l,r,val;
    	node(){
    	    //do somethings.
    	}
    };
    
    结构体的构造函数和结构体名字对不上。(然鹅,在GCC较老的版本(特指Dev-C++)中这个不会CE。)(但是NOI的GCC和某些OJ上的Clang并不认,交上去还是会CE。)所以Dev-C++背锅!
  2. struct node{
        int a,b;
        //do somethings.
    };
    bool operator<(const node& _)const{
        return 1;
    }
    
    你并不能在结构体外这样重载运算符。
  3. signed mian(){
        //do somethings.
        return 0;
    }
    
    面~函数。
  4. 在比赛快要结束时,你突然发现某题会爆 int,于是你:
    #define int long long
    
    然鹅你:
    int main(){
        //do somethings.
        return 0;
    }
    
    所以,在这里倡导大家多使用signed main代替int main

会RE

  1. int f[21][maxn];
    //do somethings.
    	for(rg int j=1;j<21;++j){
    		for(rg int i=1;i<=n;++i){
    			f[i][j]=f[f[i][j-1]][j-1];
    		}
    	}
    
    你的倍增数组的倍增维在第一维还是第二维?
  2. 你的代码中有各类UB行为,这些本来不会有大问题,然鹅你开了O2。
  3. 你的线段树build了吗?
  4. 你的平衡树插了inf-inf防止越界了吗?(如果是fhq-Treap当我没说)
  5. void work(int mid){
        for(rg int i=1;i<=n;++i){
            while(front!=rear&&slope(q[front],q[front+1])<sum[i]) ++front;
            //do somethings.
            while(front!=rear&&slope(q[rear-1],q[i])>slope(q[rear-1],q[rear])) ++rear;
            //do somethings.
        }
    }
    
    你的(单调)队列 pushpop 的时候分清 ++-- 了吗?
  6. signed XXX(){
    	//do something,but return nothing.
    }
    
    Windows 环境下感觉良好,Linux 环境下不开 O2 依然感觉良好,开了 O2 后 mmp。(问题是这玩意一旦写出来本地基本查不出来)心理:tnnd 为什么不 RE!
  7. const int N=100005;
    int rev[N],lgn,len;
    int A[N],B[N],C[N];
    void NTT(int* F,const int len,const int opt){ 
    	//......
    }
    
    NTT/FFT 的数组 tm 要开四倍。

会TLE

  1. zz の jb 火车头并不能拯救一切常数问题。

会MLE

会WA

  1. 您审题了吗?
  2. 写珂朵莉树等用到 std::setstd::map 的场合时:
    struct node{
    	int l,r; mutable int v;
    	node(int l=0,int r=0,int v=0):l(l),r(r),v(v) {}
    	inline bool operator<(const node& _)const{ return l<_.l; }
    };
    set<node> t;
    int XXX(){
    	int ret=0;
    	for(set<node>::iterator i=t.begin();i!=t.end();++i){
    		//do somthing.
    		t.erase(i);
    	}
    	return ret;
    }
    
    std::setstd::map 内部实现都基于红黑树,插入和删除时树的结构都会发生变化,结束就是迭代器失效。别 tm 为了卡一点常数边遍历边修改!