大概就是一條鏈一條鏈的處理(「鏈」在這裡指重鏈),對於每一條鏈,對於其上每乙個點,先算出它自身和所有輕兒子的貢獻,當做這一步中這個點的「權值」,然後就變成序列上dp,直接用線段樹維護
線段樹版本o(n*log^2)
1 #include2 #include3 #include4view codeusing
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 }
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解決,本質都是將樹拆成鏈,這裡用樹剖。設 ...