關於重複定義變數與memset函式導致超時的分析
阿新 • • 發佈:2020-11-25
簡述
先上倆組程式碼
code1:
void solve(){ int n; PII a[200010];//注意此處 cin>>n; rep(i,1,n){ cin>>a[i].fi; a[i].se=i; } sort(a+1,a+1+n); a[n+1].fi=INF; a[0].fi=INF; int k; rep(i,1,n){ if(a[i].fi!=a[i-1].fi&&a[i].fi!=a[i+1].fi){ cout<<a[i].se<<endl; return; } } cout<<-1<<endl; } int main(){ int t; cin>>t; while(t--){ solve(); } return 0; }
code2:
void solve(){ int n; n=read(); PII a[n+10];//注意此處 rep(i,1,n){ a[i].fi=read(); a[i].se=i; } sort(a+1,a+1+n); a[n+1].fi=INF; a[0].fi=INF; int k; rep(i,1,n){ if(a[i].fi!=a[i-1].fi&&a[i].fi!=a[i+1].fi){ write(a[i].se); printf("\n"); return; } } cout<<-1<<endl; } int main(){ int t; t=read(); while(t--){ solve(); } return 0; }
顯然上面倆組程式碼只有註釋處不同,我們將其拿到cf上交倆發
code1耗時
code2耗時
倆個程式碼耗時竟然相差了十倍!!!!!!!
分析
當輸入資料為\(t=2e4\),
接下來跟著\(2e4\)組
\(n=3\)
\(a_1=1,a_2=1,a_3=1\)
每次while迴圈中會重複定義一個2e5的陣列a,此處的a顯然為區域性變數,眾所周知區域性變數會在本次執行完成後進行銷燬操作,可能是此處的申請空間與銷燬空間耗時太多,導致時間花費較大,具體的情況筆者也不瞭解,此為猜測,不太懂編譯原理相關的東西.
再來看看定義一個\(2e5\)大小的全域性變數,每次在\(solve\)中使用memset(a,0,sizeof a)
for(int i=1;i<=2e5;i++) a[i]=0
,當輸入上面的資料時,時間複雜度為
\[O(1e4*1e5)=1e9
\]顯然\(c++\)一秒內是跑不完的,導致超時
使用memset的解決方案:
將memset(a,0,sizeof a)
換成for(int i=1;i<=n;i++) a[i]=0
即可
此時依舊執行上面的樣例,時間複雜度為\(O(2e4*3)\),顯然很快
記錄一場cf被hack的經歷
本來的code1為cin/cout輸入輸出,直接被某同學當場hack掉
code1為加入快讀版本,在cf選手的不斷努力下從800+ms跑到998ms,極限ac
珍愛\(rating\),避免不好的程式碼習慣(大霧)