1. 程式人生 > >[合集]國慶休閑補題

[合集]國慶休閑補題

元素 lin 時間 choose https 能力 缺少 最小值 gtb

Hrbust - 1846

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

容斥+dp

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

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

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

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

兩部分加起來就可以了

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


HDU - 4370

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

\(X_{i,j}\)滿足約束第1行的和為1,第\(n\)列的和為1,其余的第\(i\)

行的和等於第\(i\)列的和

使得\(\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(把行列看作點)

[合集]國慶休閑補題