永遠記住:是根據思路來想需要的演算法。而不是用思路來契合演算法。
調不出來時多造幾組樣例,以躺平、無所謂的心態去調
可以通過思考部分分來取得正解,比如菊花圖、煉圖。
不要隨便開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 萬能標頭檔...