[合集]國慶休閒補題

Hrbust - 1846

題意:序列每一個格子容許放O和X,求長度爲n的序列中至少存放m個連續的O的方案數ubuntu

\(dp[i]\)爲長度爲\(i\)時的合法方案數優化

轉移的個數來自於上一個狀態的合法序列後面接上O和X,既\(dp[i-1]*2\)spa

也有可能來自於原本不合法的方案,轉移後就合法了,那先固定一部分狀態,由於轉移後才合法,因此假定序列中[i-m+1,i]所有爲O,那麼前面就能夠隨心所欲,有\(2^{i-m}\)個狀態,但\(2^{i-m}\)中會有合法方案的存在,所以須要減去已經合法的\(dp[i-m]\)個方案,剩下的是不合法的方案後面接上\([i-m+1,i]\)的全O的方案數.(然而這連樣例都過不了)code

YY了一下認爲多是非法方案轉移途中還不到最後一位就合法了,而這已經囊括在\(dp[i-1]\)的範疇中,因此後半部分方程歪掉了,那就在\([i-m+1,i]\)置爲O,而\(i-m\)處置爲X,表示必須轉移到最後一位才能造成合法的方案,那麼轉移用到的非法方案數爲\(2^{i-m-1}-dp[i-m-1]\)get

兩部分加起來就能夠了ast

https://paste.ubuntu.com/p/mYQPpgTb9N/class


HDU - 4370

給定\(n*n\)矩陣\(C_{i,j}\),求構造一個\(n*n\)的01矩陣\(X_{i,j}\)擴展

\(X_{i,j}\)知足約束第1行的和爲1,第\(n\)列的和爲1,其他的第\(i\)行的和等於第\(i\)列的和map

使得\(\sum C_{i,j}*X_{i,j}\)最小方法

因爲劇透,得知轉化爲圖,節點1的出度爲1,節點n的入度爲1,其他\(1<i<n\)節點入度等於出度,\(C_{i,j}\)\(i→j\)的權值

入度與出度相等意味着非起始點/終點或是可能有環,須要分別討論1和n是否各自造成環,或者只是1到n的簡單路徑,對比一下權值便可

https://paste.ubuntu.com/p/pY2gVmJxkf/


FZU - 2234

題意:求雙調最短路的最大價值

來回的過程可看做是兩我的同時在起點走到終點,但物品只能取一次,但時間沒法承受\(O(n^4)\)

由於走的是最短路,對於某我的已經走了\(k\)的長度,能夠獲得\(x_i+y_i=k+2\)

所以設\(dp[k][x_i][y_i]\)爲走了k的長度時第一人在橫座標\(x_i\)而第二我的在橫座標\(x_j\)的最大價值

若是座標相等則把兩個物品的價值除二看做只拿一次

https://paste.ubuntu.com/p/nssf9KynCF/


Codeforces - 337D

題意:給出一棵n個點的樹和m個標記的點,求存在多少個點離最遠的標記點不超過d

不錯的樹形DP(換根大法好)

\(f[i]\)\(i\)\(i\)子樹下距離標記點最遠的距離,若不存在則爲\(-\infin\)(保證後面加法的正確性)

\(g[i]\)\(i\)\(i\)子樹之外的距離標記點最遠的距離,若不存在則爲\(-\infin\)

那麼答案就是\(max(f[i],g[i])≤d\)\(i\)的個數

\(f[i]\)很容易搞,只需\(f[u]=max(f[u],f[v]+1)\)

\(g[i]\)則須要考慮\(i\)的父親以及\(i\)的兄弟,\(g[u]=max(g[u],g[fa]+1,f[v]+2)\)

很顯然每一個\(u\)對兄弟\(v\)的枚舉能夠被菊花樹卡飛

那麼須要一個簡單優化,記錄對於每一個節點\(fa\)記錄\(f[]\)最大的兒子節點\(best[fa]=v\)

那麼對於枚舉到原本就是一個父親的\(best\)節點\(u\)時,對\(g[u]\)則須要暴力枚舉全部兄弟,而不是\(best\)的節點時,\(g[u]=max(g[u],g[fa]+1,f[best[fa]]+2)\)

https://paste.ubuntu.com/p/9JcQYSjGHx/


Codeforces - 675E

題意:\(n\)個車站,每一個車站\(i\)可花費用1到達車站\([i+1,a_i]\),設\(p[i][j]\)\(i\)\(j\)的最小費用,求\(\sum_{1≤i<j≤n}p[i][j]\),\(n<10^6\)

代價爲定值下可貪心的dp

\(dp[i]\)\(\sum_{i≤u<v≤n}p[u][v]\),那麼答案就是\(\sum_{i=1}^{n-1}dp[i]\)

考慮怎麼轉移,首先能夠知道的是對於\(i→[i+1,a_i]\)費用爲1,\(i→[a_{i+1},a_{i+2},...,a_{a_i}]\)費用爲2,以此類推

\([a_{i+1},a_{a_i}]\)是非單調的,仍須要維護最大值讓每次轉移儘可能遠,令這個存在最大值的下標爲\(m\)

那轉移方程就是\(dp[i]=dp[m]+[(n-i)-(a_i-m)]\)

YY一下正確性,每次轉移都按照這樣的貪心策略,對於每個\(i\)而言確定是一種最快到達\(n\)的方案之一?

其實這樣看的話這題不算是DP,只是一種記憶化手段

https://paste.ubuntu.com/p/xwHRv4SqSn/


Hrbust - 1256

題意:給出\(n\)我的,要求組建\(k\)支隊去打鐵,每支隊的戰力爲\(a[i]+a[j]+a[k]+b[i][j]+b[i][k]+b[j][k]\),求最高總戰力

範圍\(n<19\)狀壓DP優化

首先\(O(n^3*2^n)\)沒戲,須要壓常數,參考dalao的發言,因爲狀態老是3個出現,與其暴力三層枚舉,不如用k-1次湊數來更新答案,這樣複雜度是\(O(能過)\)

https://paste.ubuntu.com/p/2wd72Ddg6B/


Codeforces - 611D


HDU - 6070

題意:求\(\frac{cnt[l,r]}{r-l+1}\)的最小值,\(cnt[l,r]\)表示區間\([l,r]\)的數值種類

分數規劃問題考慮二分答案\(mid\),有\(cnt[l,r]≤(r-l+1)*mid\),次數須要維護種類數和長度的關係,很差check

把式子改成\(cnt[l,r]+(l-1)*mid≤r*mid\),每次check枚舉右端點,左邊用線段樹更新答案,每次插入新的r更新只會影響cnt的值,只要記錄各種型前一個值在哪便可,既維護一個動態的後綴

(感受本身的counting能力太弱了)

https://paste.ubuntu.com/p/dtDGK6YPJT/


Codeforces - 817D

題意:求\(\sum max(a[l,r]) - \sum min(a[l,r])\)

喜聞樂見單調棧

首先求最小的部分,

對於每一個\(i\),它能擴展到的極左邊界爲\(l[i]\),使得\(a[j]>a[i],j∈[l[i],i-1]\),並對應求出極右邊界\(r[i]\),使得\(a[j]≥a[i],j∈[i,r[i]]\)

此時\(i\)對答案的貢獻爲\((i-l[i]+1)*(r[i]-i+1)\),注意包含\(i\)的區間個數應該是兩邊都有\(i\)的交集!

同理,維護最大的部分,對於每一個\(i\),\(a[j]<a[i],j∈[l[i],i-1]\),而且\(a[j]≤a[i],j∈[i,r[i]]\)

https://paste.ubuntu.com/p/kY2Ws2bfG6/


Codeforces - 478D

題意:r個紅方塊和g個綠方塊,要求第\(i\)行搭\(i\)個同色方塊,求總共有多少種方案

垃圾題目,浪費時間

\(dp[i][j]\):第\(i\)層用了\(j\)個紅方塊的方案數,而後分別用紅方塊和綠方塊轉移便可,注意細節

尤爲是sum的break判斷不要放在while底部,由於這樣h多是恰好缺乏的那一層

https://paste.ubuntu.com/p/jQJxsVmHcB/


Codeforces - 366C

題意:給出\(a[1...n],b[1...n]\),求\(\frac{\sum a[i]}{\sum b[i]}=k\)\(\sum a[i]\)儘可能大的集合方案,輸出\(\sum a[i]\)

總費用爲0的揹包

因爲是集合,每一個元素最多隻能拿一次,且要求價值和最大,符合01揹包的背景

把式子展開爲\(\sum a[i]-\sum k*b[i]=0\),能夠看出體積爲\(a[i]-k*b[i]\),價值爲\(a[i]\)

對着跑一遍01揹包就ok,目標是\(dp[n][0]\)

做死嘗試unordered_map

https://paste.ubuntu.com/p/BkyMYqxzPJ/


Codeforces - 466D


HDU - 2833


HDU - 5242


Codeforces - 489F

題意:已知前m行01矩陣,求構造\(n*n\)的01矩陣使得每一行列只有2個1的方案數

\(dp[i][j][k]\):當前第\(i\)行的列和爲0的總數是\(j\),列和爲1的總數是\(k\)

因爲要求每一行都要由2個1,就是說轉移過程當中新構造的一行必須填入2個1,這是突破口

\(dp[i][j][k]=dp[i-1][j+2][k-2]* {j+2 \choose 2} + dp[i-1][j+1][k]*(j+1)*(k)+dp[i-1][j][k+2]*{k+2\choose 2}\)

目標是\(dp[n][0][0]\)

但這樣會T

一種解決方法是枚舉\(i\)行和\(j\)個位置,能夠計算獲得\(k=(n-i+1)*2-j*2\)

https://paste.ubuntu.com/p/rjNc844Hcj/


HDU - 2853


HDU - 4360


Ural - 2080

觀賞題:CF669D/51nod-1021/HDU4101/

OJ掛了:CSU1809

回收站:HDU4472/CF550C/CF660C/CF353D/Hrbust1774/CF430D

建圖相關:CF821D(把行列看做點)

相關文章
相關標籤/搜索