洛谷P4719 模板 動態dp

2022-05-21 19:18:09 字數 2066 閱讀 9074

大概就是一條鏈一條鏈的處理(「鏈」在這裡指重鏈),對於每一條鏈,對於其上每乙個點,先算出它自身和所有輕兒子的貢獻,當做這一步中這個點的「權值」,然後就變成序列上dp,直接用線段樹維護

線段樹版本o(n*log^2)

1 #include2 #include3 #include4

using

namespace

std;

5 typedef long

long

ll;6

structe7

e[200011

];10

int f1[100011

],ne;

11struct

p112;15

struct

p216

;19 ll a[100101

];20

int sz[100101],hson[100101],ff[100101

];21

int b[100101],pl[100101

];22

intn,m;

23inline ll max1(ll a,ll b)

2427

const ll inf1=-0x3f3f3f3f3f3f3f3f;28

#define max max1

29#define g(x) max1((x),inf1)

30 inline void merge(p1 &c,const p1 &a,const p1 &b)

3141 inline void initnode(p1 &c,const p2 &a)

4246

namespaces47

52 p1 x;int

l;53

void _setx(int l,int r,int

num)

5460

int mid=(l+r)>>1;61

if(l<=mid) _setx(l,mid,lc);

62else _setx(mid+1

,r,rc);

63upd(num);64}

65 p1 getx(int l,int r,int l,int r,int

num)

6675

else

if(l<=mid)

76return

getx(l,r,l,mid,lc);

77else

if(mid

78return getx(l,r,mid+1

,r,rc);

79else

80 exit(-1

);81}82

}83void dfs1(int u,int

fa)8495}

96 p2 d1[100101];//

d1[i]維護i節點及其輕兒子的貢獻

97 p2 d2[100101];//

d2[i]維護i節點(是重鏈頂)所在重鏈的dp值

98int tp[100101],dwn[100101];//

鏈頂,鏈底

99void dfs2(int u,int

fa)100

115 initnode(s::x,d1[u]);s::l=pl[u];s::_setx(1,n,1

);116

if(u==tp[u])

117122

}123

intmain()

124134 dfs1(1,0

);135 dfs2(1,0

);136

while(m--)

137153

//printf("%lld %lld\n",d2[1].d[0],d2[1].d[1]);

154 printf("

%lld\n

",max(d2[1].d[0],d2[1].d[1

]));

155}

156return0;

157 }

view code

bst版本o(n*log)

待寫

洛谷P4719 模板 動態 DP

給定一棵 n 個點的樹,點帶點權。有 m 次操作,每次操作給定 x,y 表示修改點 x 的權值為 y 你需要在每次操作之後求出這棵樹的最大權獨立集的權值大小。調到心態 從前天晚上開始就剛這道題。最大權獨立子集即 選出若干個不相鄰的點使得他們的權值最大 摘自akioi的神仙 若沒有修改,這道題就是樹形...

洛谷P4719 動態DP模板

一棵 n 個點的樹,點帶點權。m 次操作,每次操作給定 x,y 表示修改點 x 的權值為 y 每次操作後求出這棵樹的最大權獨立集的權值大小。n,m leq 10 5 首先有乙個 o nm 的 dp 設 f u 0 1 分別表示以 u 為根的子樹中,u 不選 選 的最大獨立集權值大小。f u 0 su...

luoguP4719 模板 動態 DP

我理解的動態dp 發現dp可以寫成矩陣的形式,因此用資料結構維護矩陣乘積。對於這道題,顯然有dp f 表示 x 的子樹中,x選 不選的最大點獨立集。f sum limits max f f f sum limits f a x 既然在樹上,就用樹剖或者lct解決,本質都是將樹拆成鏈,這裡用樹剖。設 ...