OI做題方法總結

2022-05-26 19:00:12 字數 3607 閱讀 9875

永遠記住:是根據思路來想需要的演算法。而不是用思路來契合演算法。

調不出來時多造幾組樣例,以躺平、無所謂的心態去調

可以通過思考部分分來取得正解,比如菊花圖、煉圖。

不要隨便開long long,常數大

考試時注意時間分配

樹論的題,不是資料結構要麼dp要麼推結論貪心

看完題目先模擬一下樣例,能摸出很多性質

找出有用的性質這題就成功了一半了。

還有就是要把演算法/資料結構看作手中的工具,靈活運用,改造,堆疊在一起使用

一般一道題就三種切入口

直接做考慮題目是否有單調性或貪心性

用資料結構來加速模擬過程或是維護修改等

數型結合?轉化成圖或樹結構?

dp:記得寫初始值,清空陣列,想清楚列舉邊界和遞推式的使用條件,這對答案的正確性影響很大

陣列:線段樹開4倍,雙向邊開2倍,要動態開店或者可持久化的能開多大開多大。

常用方法:

貪心樹形dp

重鏈剖分

長臉剖分(多用於優化dp)

點分治(聯通塊有關問題,比如求樹中指定距離的點對個數)

樹上莫隊(如果要求路徑資訊考慮用尤拉序列,即每個點dfs開始和結束都放入序列內,並標記是進入還是退出)

注意點分治的過程中要維護乙個isroot[i]陣列,標記i是否曾今當過重心,getroot,divide,getdep函式碰到isroot[to]=true的點都要避開(否則等著tle吧)

注意樹形揹包的複雜度是$nv$的

樹形dp的思考方式一般是

考慮葉子向其父親的貢獻(一片兩片三片地遞增地考慮)

然後再逐層往上考慮,總結性質

如果題目中有操作之類的,考慮樹鏈剖分維護

詢問路徑的最值或方案數之類的,考慮用路徑拼接,有兩種常見方法

樹形dp,開乙個維度標記已經決定了多少個端點

每乙個點從兒子那繼承一堆這個點為起點,終點在子樹內的路徑,然後拼接

一些方法&結論:

如果有奇偶等限制,考慮黑白染色

對於既有邊權又有點權的圖,考慮把它們集中於點上

樹上維護資訊的題,考慮啟發式合併(二維樹形dp或維護方案)

按大小分輕重兒子:重鏈剖分

按長短分輕重兒子:長鏈剖分

換根操作:可以用分類討論避免換根導致的子樹資訊重置。

比如上面這張圖,原本的根是最高的那個。

現在要把紅色的點換為根。

那麼原圖只有新根的祖先會收到影響。即,他們的子樹變為了整棵樹除去【它到新根的那個兒子的子樹】 。

這樣它的子樹的區間會被拆成乙個字首區間乙個字尾區間。可以考慮將dfn序列倍長,將字首拼到字尾後面去。

其他綠色點的子樹資訊均不受影響。

遇到求指定範圍森林裡樹的個數,即在全部是樹的環境中求聯通塊個數,考慮如下結論:樹的個數=點數-邊樹。

樹的重心一定在從根節點出發的重鏈上,故除dp外我們還可以從根節點出發沿重鏈前進,遇到第乙個點滿足父親那一塊面積小於總大小的一半。(csp-s d2t3)

在樹上求經過一些點的最短路徑,這條路徑等於這些點的最小生成樹的兩倍,且一定是按照這些點的dfs序依次經過([sdoi2015]尋寶遊戲)

圖的核心思維就是把圖問題轉化為樹問題求解

圖的常用方法不多,大概就以下幾種

tarjan

最短/長路

最小/大生成樹

並查集如果有限定恰好幾步或是多層結構一樣的圖,考慮矩陣快速冪優化(把鄰接矩陣相乘k次就是走了k步後的距離矩陣)

若圖論中要大規模建邊,考慮線段樹優化建邊(【bzoj3218】a + b problem,[cf787d] legacy  )

圖論dp可以點數較小時,dp層數較多時可以考慮矩陣乘法優化(「bzoj1875」[sdoi2009] hh去散步)

有向圖dp時,若可以走回頭路,則情況會很複雜,考慮先縮點變成dag,再dp

有些題目無法直接構造,可以轉化為每個要求為一些限制,求這個限制系統有無解。(比如csp-s d1t3).檢查可以通過並查集、鍊錶、拓撲排序、搜尋完成。

要在乙個序列的基礎上生成乙個排列,可以考慮轉化為圖論問題,從i向$a_i$處連邊。

常用方法:

貪心dp

二分網路流(其實可以看作一種帶反悔的貪心或者dp)

模擬退火(不會)

網路流有時可以考慮用資料結構模擬。

貪心有時可以和dp結合起來用

(其實很多方法都是通的,可以搭配起來用)

題型:求一些滿足某些限制的方案數

常見套路(也是結合起來用)

正反互換:用總方案數-不滿足限制的方案數

排列組合

容斥(有$o(n)$和$o(2^n)的$

dp有些題目需要去重,可以考慮重複的方案有什麼共同的性質,再體現在**中。

如果要求的是恰好有k個滿足的情況數,但只能求出至多或至少的情況數,考慮組合容斥。

先考慮最樸素的dp方式

然後再考慮優化

但是要注意正確性

刪減狀態:一些意義相近的狀態或許可以合併,或者可以用一些性質省略掉的,比如差分等操作(emiya家今天的飯)

資料結構優化:單調佇列,斜率優化,線段樹/樹狀陣列,堆等

同構dp方程優化:

對於每乙個位置的dp方程都一樣,沒有判斷句等東西影響,可採取這種優化。

f[i][j],i很大,j在n^3範圍內,矩陣快速冪

f[i][j],i在n^2範圍內,j很大,且轉移方程沒有min,max之類的東西:拉格朗日插值,盲猜次數<=n

也可以考慮是否能交換i,j的列舉順序

概率dp,有可能遞推到後面概率變化很小,這樣就不需要推完整個n。

這種題就應該上大資料結構來搞

維護顏色數、mex考慮莫隊、主席樹、分塊,也可以考慮維護乙個pre[i]陣列表示上乙個與這個位置相同顏色的的位置(noi online t2)

計算一堆區間函式,乙個乙個函式統計是比較低效的,可以從貢獻的角度考慮 

線段樹/樹狀陣列

平衡樹(節點並不一定代表乙個位置,也可以代表一段區間)

分塊倍增

樹鏈剖分(樹中路徑的維護)

點分治(樹中指定距離內區塊的維護)

lct(帶刪連邊操作的)

離線莫隊

整體二分

cdq有個套路就是維護區間min,max,相當於在操作區間內找出乙個分割點分開處理

有些區間推平操作可以用維護min,max的方式來維護

區間整數除法可以維護min,max,然後看作區間減法來處理

若要求序列中每個點的left[i]和right[i],即左邊和右邊距離它最近的且比它大\小的點,用單調佇列兩邊各跑一次即可

求最長上公升\下降子串行可以用樹狀陣列做到nlogn,即正序列舉對於已經計算完的j,把dp[j]插到樹狀陣列中的val[j]處。val[j]為第j位的權值,計算dp[i]=樹狀陣列中[1,val[i]-1]區間的最大dp值+1,然後再把dp[i]插入。這樣需要對權值進行離散化。

除了遍歷外,可以用dp初始化陣列

bool開桶開不下可以考慮bitset

o(1)統計乙個數二進位制位的一的個數:先預處理$2^$以內的數的答案,然後將目標數不斷除與$2^$

期望具有可加性,即兩個隨機變數的和的期望等於兩個隨機變數的期望的和,即$e(x+y)=e(x)+e(y)$

03 04做題總結

3 4 月做題總結 題目鏈結 主要思路 確定比賽名次 拓撲排序 奇怪的夢境 拓撲排序判環 逃生反向拓撲 儀仗隊o尤拉函式 秦隊長的猜想 g哥德 猜想 棋盤問題 dfs 回溯 非常可樂 bfs or 數論 表示式求值 m模擬legal or not t拓撲排序 產生冠軍 t拓撲排序 reward 拓撲...

做題總結 Pawn s Revenge

題目描述 這道題目自己一開始時也沒有思路 後來才發現其實也並不難,實在是學的不太好 後來從網上查詢了一些資料,大概明白了這道題目的思路。這道題目是在已經有且只有乙個k棋子的情況下,通過增加最少數量的的pawn棋子,能夠將對方的所有的 棋子全部攻擊到,其中k能夠攻擊其餘八個方向,pawn棋子只能攻擊左...

做題總結 Latin Squares

原題 題意分析 題目就是輸入乙個二維陣列 用來表示矩陣 判斷對於矩陣中的每乙個數字是否在該數字所在的行 所在的列的只出現一次 相當於數獨的概念 如果是的話,則該矩陣是拉丁方,再判斷矩陣的第一行 第一列的元素是否按照公升序的方式排列的,從而進行對應的判斷輸出 做題思路 實現 include 萬能標頭檔...