有些東西借鑑了這裏qwqgit
1.IO(istream/ostream) 輸入輸出優化程序員
以後能,在賽場上常見的幾種輸入輸出:算法
輸入:緩存
$1.cin$ 呵呵,不說什麼了,慢的要死。大概$1e8$個數要讀1分鐘左右數據結構
$2.scanf, \_ \_ builtin \_ scanf()$ $scanf$ 其實還不算太快,可是$\_ \_ builtin \_ $在$NOIp$賽場上會$CE$ 函數
$3.read()$ 美其名曰:讀入優化(反正本寶寶不會),在各大神犇的提交記錄以及題解上隨處可見,親測確實比$scanf$要快許多優化
代碼大概長這樣: $by\ Young\ Neal$ui
int getint(){ int x=0,f=0;char ch=getchar(); while(!isdigit(ch)) f|=ch=='-',ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return f?-x:x; }
$4. fread$ 歡迎來自$AK$爺的飛速文件讀入輸出spa
struct file_io{ #define isdigit(ch) ((ch) >= '0' && (ch) <= '9') char inbuf[1 << 25], *pin, outbuf[1 << 25], *pout; int stk[20]; file_io(): pout(outbuf) {fread(pin = inbuf, 1, 1 << 25, stdin);} ~file_io() {fwrite(outbuf, 1, pout - outbuf, stdout);} inline void getint(int &num){ bool neg = 0; num = 0; while(!isdigit(*pin)) if(*pin++ == '-') neg = 1; while(isdigit(*pin)) num = num * 10 + *pin++ - '0'; if(neg) num = -num; } inline void putint(int num){ static int *v = stk; if(!num) *pout++ = '0'; else{ if(num < 0) *pout++ = '-', num = -num; for(; num; num /= 10) *v++ = num % 10; while(v != stk) *pout++ = *--v + '0'; } } inline void nextline() {*pout++ = '\n';} } fio; #define getint(num) fio.getint(num) #define putint(num) fio.putint(num) #define nextline() fio.nextline()
輸出:code
$1.cout$ 呵呵,和$cin$一個樣
$2.printf , \_ \_ builtin \_ printf$ 已經比上面那個快多了,可是同樣,$\_ \_ builtin \_ printf$會$CE$
$3.puts("")$ 對於已知字符串來講,能用 $puts()$不用$printf()$ 可是$puts("")$輸出以後會換行
$4.fio$見上面 (STO GhostCai)
固然了,在$NOIp$範疇內,輸入輸出量並不算太大,多數$printf(),scanf()$就能夠了,
除非$……$
你是要暴力碾標算而後再去$diss$一頓出題人數據水的神犇$……$
這時候讀優就必不可少了。
2.內存優化
某$shadowice1984$大佬最擅長的東東,如下引用$shadowice1984$給本寶寶講課時候的話:
「咱們的$CPU$要對某一個數進行計算的時候,會先在一級緩存中找這個數的地址要是找到了,直接揪過來~~槍斃~~進行計算,速度很快的,
可是一級緩存能儲存的東西不多,就是幾個$int$,若是沒有找到,成爲'一級緩存未命中',可是,這時候,咱們還有一個二級緩存和三級緩存,一樣,也很很快,
而‘三級緩存未命中’以後,卻要去內存裏找這個東西了,這裏面會經歷虛擬地址與物理地址的互相轉換而後還有$……(\text{此處省略})$而後耗時巨大(相對於從緩存直接調用來說)。
這是後,咱們就會稱爲$cache\ miss$,而若是咱們的程序由於$cache\ miss$的次數太多而致使常數因子看似特別大(理論複雜度正確可是就是$tle$),就習慣的成爲卡$cache$」
當本寶寶聽完這段話以後,
哇$……$真是一個暴力碾標算的好方法
那麼$……$咱們怎麼才能減小$cache\ miss$呢?
$1.$保證內存的連續訪問
這就是爲何本寶寶鄰接鏈表寫的每次都比別人慢上差很少一倍$qwq$ ,由於如今只有本寶寶用結構體寫了啊啊啊啊啊啊!
$2.$多個$for$循環能夠適當調整順序
最明顯的就是矩陣乘法和$Folyd$算法了,對於$folyd$ $(eg. \ NOIp2016 \text{換教室})$
for(int i=1;i<=n;i++) for(int j=1;j<i;j++) for(int k=1;k<=n;k++) d[i][j]= d[j][i]=min(d[i][j],d[i][k]+d[k][j]);
for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<i;j++) d[i][j]=d[j][i]=min(d[i][j],d[i][k]+d[k][j]);
親測第二種寫法會比第一種寫法快好多呢。
矩陣乘法同理,
for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) c.num[i][j]+=a.num[i][k]*b.num[k][j];
把$k$這一維放到外面明顯比放到裏面要快
3.register 與 inline
$register$在$for$裏面真的會快一點,用法就是$for(register int i=1;i<=n;i++)$
$inline$ 只能用在沒有遞歸的函數裏,其實手動$inline$是個很好的東西,可是不必定。
這兩個有的時候會形成負優化,這就呵呵了。
4.(僅限於$NOIp$等不開$O2$的賽事上) 手寫$stl$
$stl(\ C++ \ Standard\ Template \ Library \ )$ 確實特別好用,也是$C++$的精華所在,
能夠爲程序員們節省很大的時間,
可是,在不開$O2$的狀況下,會由於種種緣由慢的要死,
儘可能背過一些簡單的數據結構,能少用就少用。
5.玄學(信仰)優化:
(1). 打表優化
若是有的寫的非正解,可是又想拿高分,全打表得話會超過代碼長度限制,這是後能夠部分打表,記得作過一道題
對於30%的數據,知足n<=500;
對於100%的數據,知足n<=1000;
而後我和$shadowice1984$都會一個$On^{3}$的方法,顯然確定過不了$1000$
以後,本寶寶放棄了,拿了$30$分去一邊哭去了,
$shadowice1984$,$n^{3}$信仰過$500$,而後又信仰的打了一下$n=995$到$n=1000$的表
而後就$……$ 而後就 $A$ 了
數據範圍內,只打極限數據,放心,出題人必定會很毒瘤的
還有優化打表的方法:查分優化,二次查分優化,$26$進制壓縮($eg.$樹的平均路長問題)
(2).女裝優化(親測有效)
女裝能夠大大的減小$bug$和常數,真的親測有效,模擬賽的時候$t$的東西,**後再測就過了。。
(3).神犇優化(親身經歷)
有一次網上打$nowcoder$的比賽,而後和旁邊的神犇代碼比較一下只有變量名不一樣(纔不是互相抄的呢)
而後$……$人家神犇就過了,本寶寶就$T$了,
平時作題的時候,本寶寶常常出現用時和神犇差距很大,
本身寫線段樹都已經不記錄$l,r$了,還比那些開結構體記錄$l,r$的神犇慢$……$
真的是人菜常數大,真的是$……$
~~因此想暴力碾標算的話,先要成爲神犇~~
(4).信仰優化
$srand(1926****)$ $srand(\text{cp或神犇生日})$
$eg.\ srand(20020902) \ \ srand(20020224) $
(左cp右神犇)
而後當你
printf("%s",rand()%2?"Yes":"No")
的時候會增大$AC$率的 ($NOIp2017\ \ D1\ \ T2$)
但願有用(光速逃~)