說實話這個問題之前一直沒有意識到,後來才發現這門學問是如此高深,本著精益求精的態度,有些時間空間的高度優化還是必要的,有時候可能就跟爐石里的伏筆似的,所以即使在做最簡單的問題的時候其實也能有一些不錯的想法。由於這個問題十分高深,所以我也沒有辦法絕對說明,也是慢慢研究中的,但我會不斷更新,把我所有的研究成果彙總整理到這裡,war3裡的女巫說過「help me , help you」我想還是有一定道理的。
事先說明,很多成果都有我借鑑的成分,是很多聚聚們優秀智慧型的結晶,再次膜拜他們。
先用一道簡單題來作為開頭吧——xdoj1024簡單逆序對
來看看兩個**
a
# include
# include
const
int max_n = 2e6;
const
int mod = 1e9 + 7;
char s[max_n];
int box[10];
int t, n;
int main()
printf("%lld\n", ans % mod);
}return
0;}
b
# include
# include
const
int max_n = 2e6;
const
int mod = 1e9 + 7;
char s[max_n];
int box[10];
int t, n;
int main()
printf("%lld\n", ans % mod);
}return
0;}
可能很多認覺得這兩個**沒有什麼特別不同的地方,但是結果卻是顯著的。可以看一看
可以看到空間一欄沒有區別,但是時間一欄卻相差了近6倍,那麼很多人可能好奇這是在列印了多少組數的結果呢,我可以很確定的告訴你,這道題的測試資料只有1e6左右,也就是說在一行1e6的情況下常規的scanf比用字串輸入一行的gets慢了280ms,這是多麼恐怖的乙個數字,所以這也讓我有了研究下去的動力。我們接下來繼續深層次的看看吧。
我暫時先把這個方法叫做gets**,這道題的確有一些特殊的成分,比如數字都是一位的,並且每個數字之間都保證只有乙個空格,所以為了進一步研究這個方法的普適性,我又用這個方法提交了1099簡單的問題,這道題的輸入格式和1024很相似,但是首先每個數字有好幾位,並且數字之間有兩個空格,所以需要一定的改動。這是一道尺取法的題,一般來說最優化的普通方法大約是250ms的時間,那麼用了gets優化之後的結果呢?我嘗試著寫了乙個,發現平均只需要50ms的時間,最快達到了40ms最慢也不超過60,還是很給力的。所以這個方法看起來效果是很不錯的。不過乙個小問題是我們需要研究清楚題目的格式,包括字母大小寫以及正負的問題,我打算再嘗試一些從而做出乙個比較通用的輸入模板,這樣在處理大輸入問題的時候能夠變得更好。
順便把1099的輸入優化後的**貼出來吧(並不一定是最好的)
#include
typedef
long
long ll;
const
int max_c = 1e7;
char s[max_c];
int a[100001];
int n, k, t;
int main()
else
}int sum = 0, l = 0;
ll ans = 0;
for(i = 0 ; i < n ; i++)
printf("%lld\n",ans);
}return
0;}
2018、5、26
另外說一說這個gets()的乙個很迷的問題,就是吃回車的問題,因為scanf是輸入到空格或回車結束,但是不吃他們的,所以有可能會導致那個回車被gets吃掉從而出錯,比較常規的做法是加乙個getchar,不過這個依然比較迷,因為我也遇到過什麼都不加卻對了,加了getchar卻錯了的情況,還有都錯的情況,所以在看到了在scanf後面加\n這個方法之後,感覺還是這個方法最穩,因為的確遇到了加不加getchar都錯但是加了\n之後卻對了的情況。所以用gets前這個回車的問題一定要考慮好。
再說說經典的輸入方式,和gets基本沒有區別,只不過是用getchar來進行捕獲,不過的確getchar這個要慢一些,但是好處是省記憶體,用gets的話大約需要10倍的max_n才能保險,不過大部分情況是沒問題的。另外,就算用經典的方法其實也有更快的手段,就是用getchar_unlocked代替getchar這個方法可以說是簡單粗暴地提速一倍左右,利益模擬於cin的呢個關掉什麼什麼東西(我也不用cin,所以也記不清了),理論上來說是因為單執行緒輸入雖然危險,但是快,所以在acm領域基本是沒有問題的,gets好像就是單執行緒的(用了好像會被oj警告),getchar_unlocked也是,所以再用它優化之後效果只比gets**慢一點點。
就拿1307的測試結果為例 時間
簡單gets模板 34——56
複雜gets模板(適合更多情況) 36——56
經典getchar 100左右
優化的getchar 60左右
另外貼上幾個模板以供參考
簡單gets
/*
注意事項
1因為有gets,之前如果用scanf的話結尾加/n
2陣列需要留有富裕,否則可能答案出錯
3數字之間間隔必須是乙個非數字字元
4沒有負數
*/char s[10 * max_n];
void scan(int * a)
}
複雜gets
/*
1時間上和簡單版一致(做都可以適用的問題時)
2可以處理數字間多間隔情況
3可以處理負數
4如果符合要求建議使用簡單版
注意!!!
5上乙個scanf別忘了在末尾加/n
6陣列需要留有富裕,否則可能答案出錯
*/char s[10 * max_n];
void scan(int * a)
}
經典
# define get getchar_unlocked
void scan(int n , int * a)
while(c >= 48 && c <= 57)
if(f)
a[i] *= -1;
i++;}}
破爛集 stl邪術 rope
之前做一道要用到splay的問題,因為並不會splay 同時懶得學習 所以就試圖在論壇找找有沒有偷懶的辦法,沒想到真的讓我找到了,那就是rope這個結構,這個東西聽說比較新,所以如果特別老的oj 比如poj和hdu 我覺得可能懸,不過dev 前提是新版的,不是機房那種 和牛客這些應該都可以支援。這個...
破爛集 大佬的spfa
估計所有人在看過spfa之後基本都會把其他最短路的演算法忘光吧,因為spfa不但超級簡單,而且還超級塊,所以的確非常好用,之前看到乙個大佬的spfa,感覺有幾個不錯的優化,用了之後把我1202的乙個85ms左右的演算法直接優化到65ms了,還是很給力的,所以在這裡貼一下,主要在於用deque代替qu...
Keras打亂輸入資料集
實驗資料集 2096 351,第一列為y,餘下350列為特徵x 分割輸入x和輸出y x dataset 1 351 y dataset 0 打亂訓練集 index i for i in range len dataset 下面這種寫法也可以 index np.arange len dataset n...