學習了一下動態dp
首先乙個顯然的 \(o(nm)\) 的做法就是每次做一遍樹形dp(這也是我在noip考場上唯一拿到的部分分),直接考慮如何優化這個東西。
簡化一下問題,假如這棵樹是一條鏈,那就變得很簡單了,可以直接拿線段樹維護矩陣加速。
可是如果每個點不止有乙個兒子呢?
我們首先樹剖一下。
設 \(g[i][0]=\sum\limits_ \max(f[j][0],f[j][1])\)
\(g[i][1]=a[i]+\sum\limits_ f[j][0]\)
即 \(g[i][0]\) 表示 \(i\) 的所有輕兒子的 \(\max(f[j][0],f[j][1])\) 之和,\(g[i][1]\) 表示 \(i\) 的所有輕兒子的 \(g[j][0]\) 之和與 \(a[i]\) 的和。
那轉移方程就可以改寫為 \(f[i][0]=\max(g[i][0]+f[son[i]][0],g[i][0]+f[son[i]][1])\)
\(f[i][1]=g[i][1]+f[son[i]][0]\)
還有一點就是修改的時候,要一直跳 \(top\),可以這樣理解:假設當前更改了點 \(x\) 的點權,那麼就會改變 \(f[top[x]]\) 的值,緊接著就會影響 \(g[fa[top[x]]]\) 的值,所以我們要一直向上跳 \(top\) 修改才能維護好。
最後放一下**:
#pragma gcc optimize(2)
#includeusing std::min;
using std::max;
using std::swap;
using std::vector;
typedef double db;
typedef long long ll;
#define pb(a) push_back(a)
#define pii std::pair#define all(a) a.begin(),a.end()
#define mp(a,b) std::make_pair(a,b)
const int n=1e5+5;
const int inf=1e9;
#define ls x<<1
#define rs x<<1|1
#define lss ls,l,mid,ql,qr
#define rss rs,mid+1,r,ql,qr
int tot,dfn[n],top[n],end[n];
int n,m,v[n],sze[n],son[n],f[n][2];
int cnt,head[n],g[n][2],fa[n],fs[n];
struct edgeedge[n<<1];
void add(int x,int y)
struct mat
friend mat operator*(mat x,mat y)
}sum[n<<2],val[n];
int getint()
void dfs(int now)
}void dfs(int now,int low) if(son[now]) end[now]=end[son[now]];
else end[now]=now;
g[now][1]+=v[now];
f[now][0]=g[now][0]+max(f[son[now]][0],f[son[now]][1]);
f[now][1]=g[now][1]+f[son[now]][0];
}void pushup(int x)
void build(int x,int l,int r)
void init()
mat query(int x,int l,int r,int ql,int qr)
mat ask(int x)
void modify(int x,int l,int r,int ql,int qr)
void change(int x,int y)
}signed main() f[j])\),然後套路設 \(g[i]=\sum\limits_ f[j]\),於是 \(f[i]=\min(a[i],g[i]+f[son[i]])\)。
又可以寫成矩陣相乘的形式:
\[\beginf[son[i]]\\0\end\times \beging[i]&a[i]\\\infty&0\end=\beginf[i]\\0\end
\]然後動態dp就行了。
需要注意一點的是在 \(change\) 函式裡,\(pre,nxt\) 的矩陣應該是 \(ask(top[x])\) 而不是 \(ask(x)\)。
給出一棵樹,點有點權。每次強制選或不選兩個節點,求最小權覆蓋集。
首先有個定理:最小權覆蓋集=全集-最大權獨立集。然後就是luogu模板題了。
動態 DP 學習筆記
對矩陣乘法和重鏈剖分有一定了解即可。首先我們這個題可以很簡單寫出乙個方程,設 f x 0 為不選 x 時 x 子樹內的最大獨立集,設 f x 1 為選 x 時 x 子樹內的最大獨立集,那麼有以下轉移 f x 1 val x sum f y 0 f x 0 sum max f y 0 f y 1 我們...
DP(動態規劃)學習筆記
揹包問題 01揹包每件物品最多使用一次 完全揹包每件物品有無限個 多重揹包每種物品最多有si個 存在樸素版和優化版 分組揹包沒組最多只能選 1 個 dp優化 對dp方程進行等價變形 dp最重要的就是公式推導 對於當前狀態的計算 要滿足兩個條件 不重 不漏 最簡單的01揹包 d p i j ma x ...
DP動態規劃部分學習總結
這幾天學習動態規劃,我的理解是dp大致可分為2類,一種是自下而上 也叫遞推 另一種是自上而下。這兩種方法都可以達到目的。仔細來講動態規劃是解決多階段決策問題的一種方法。並且每一步得出的結論都講影響下一階段的結果將每一階段都需要取出最佳結果然後一步步下去得出最終答案。並且動態規劃要秉承最優性原理。而最...