BZOJ4712 洪水 樹鏈剖分 線段樹

2022-05-03 18:36:09 字數 2322 閱讀 6610

小a走到乙個山腳下,準備給自己造乙個小屋。這時候,小a的朋友(op,又叫管理員)開啟了創造模式,然後飛到山頂放了格水。於是小a面前出現了乙個瀑布。作為平民的小a只好老實巴交地爬山堵水。那麼問題來了:我們把這個瀑布看成是乙個n個節點的樹,每個節點有權值(爬上去的代價)。小a要選擇一些節點,以其權值和作為代價將這些點刪除(堵上),使得根節點與所有葉子結點不連通。問最小代價。不過到這還沒結束。小a的朋友覺得這樣子太便宜小a了,於是他還會不斷地修改地形,使得某個節點的權值發生變化。不過到這還沒結束。小a覺得朋友做得太絕了,於是放棄了分離所有葉子節點的方案。取而代之的是,每次他只要在某個子樹中(和子樹之外的點完全無關)。於是他找到你。

這道題真的是666。。

我們設g[x]為堵住該點所有子樹的和,v[x]為堵住該點的代價,則f[x]=min(g[x],v[x])。現在我們要給v[x]加上to。

1,v[x]>=g[x],v[x]加多少都不會有影響,過;

2,v[x]<=g[x]&&v[x]+to<=g[x],則g[fa[x]]+=to,如果f[fa[x]]改變,則還需要接著往上推。

3,v[x]<=g[x]&&v[x]+to>g[x],則g[fa[x]]+=-v[x]+g[x],如果f[fa[x]]改變,同樣需要接著往上推。

對於情況1,直接處理掉就ok了。

我們考慮優化情況2和3的處理。在這裡我們採用樹剖+線段樹。線段樹儲存v[x]-g[x]。

對於點x,我們沿著重鏈往上,如果在某條重鏈上都是情況2或3,直接加就好;反之在這條重鏈上二分。

#include#include

#include

#include

using

namespace

std;

typedef

long

long

ll;int

n,x,y;

ll v[

200010],_g[200010],dp[200010

],d;

struct nodeg[

400010];int h[200010],tot=0

;int m;char ch[5

];int fa[200010],dep[200010],son[200010],top[200010],sz[200010

];int cnt=0,dfn[200010],id[200010

];struct

xd_tree

int mid=(l+r)/2

; build(k

<<1,l,mid);build(k<<1|1,mid+1

,r);

mn[k]=min(mn[k<<1],mn[k<<1|1

]); }

void downtag(int

k)

int modify(int k,int l,int r,int askl,int

askr,ll d)

if (askl<=l&&r<=askr)

}if (tag[k]!=0

) downtag(k);

int mid=(l+r)/2,re=0

;

if (askr>mid) re=modify(k<<1|1,mid+1

,r,askl,askr,d);

if (askl<=mid&&!re) re=modify(k<<1

,l,mid,askl,askr,d);

mn[k]=min(mn[k<<1],mn[k<<1|1

]);

return

re; }

ll query(

int k,int l,int r,int

ask)

}x;struct tree_link//

樹剖

if (sz[x]>1) dp[x]=min(_g[x],v[x]);else dp[x]=v[x],_g[x]=1e9;

}void dfs2(int

x)

void work(int

x,ll d)

x=fa[top[x]];}}

}t;ll getg(

int x)

intmain()

;h[x]=tot;

g[++tot]=node;h[y]=tot;

}t.dfs1(

1,0);

t.dfs2(1);

x.build(

1,1,n);

scanf("%d

",&m);

for (int i=1;i<=m;i++)

else

}}

BZOJ4712洪水 動態DP 樹鏈剖分 線段樹

小a走到乙個山腳下,準備給自己造乙個小屋。這時候,小a的朋友 op,又叫管理員 開啟了創造模式,然後飛到 山頂放了格水。於是小a面前出現了乙個瀑布。作為平民的小a只好老實巴交地爬山堵水。那麼問題來了 我們把這 個瀑布看成是乙個n個節點的樹,每個節點有權值 爬上去的代價 小a要選擇一些節點,以其權值和...

bzoj4712 洪水 樹鏈剖分 動態dp

我們首先想乙個dp方程 f u mi nf u min val u f u m in。這個方程可以通過矩陣的形式來表示。先把樹輕重鏈剖分了。我們設g u g u g u 為u uu的所有輕兒子的f ff總和,v vv為u uu的重兒子。則f u mi nf u min f u m in。我們可以把這...

BZOJ4712 洪水 樹鏈剖分維護Dp

小a走到乙個山腳下,準備給自己造乙個小屋。這時候,小a的朋友 op,又叫管理員 開啟了創造模式,然後飛到 山頂放了格水。於是小a面前出現了乙個瀑布。作為平民的小a只好老實巴交地爬山堵水。那麼問題來了 我們把這 個瀑布看成是乙個n個節點的樹,每個節點有權值 爬上去的代價 小a要選擇一些節點,以其權值和...