很容易写出转移方程以及状态的定义
F
[
i
]
[
0
/
1
]
:
F[i][0/1]:
F[i][0/1]:以i节点为根的子树,选/不选i节点的最大权独立集
F
[
i
]
[
0
]
=
s
i
g
a
m
(
m
a
x
(
f
[
s
o
n
]
[
0
]
,
f
[
s
o
n
]
[
1
]
)
)
F[i][0] = sigam(max(f[son][0] , f[son][1]))
F[i][0]=sigam(max(f[son][0],f[son][1]))
F
[
i
]
[
1
]
=
v
a
l
[
i
]
+
s
i
g
a
m
(
f
[
s
o
n
]
[
0
]
)
F[i][1] = val[i] + sigam(f[son][0] )
F[i][1]=val[i]+sigam(f[son][0])
然后发现,如果要修改的话,只按照上面的状态定义来做是不行的
于是可以尝试对原树进行树po
并且由此可以得到新的转移
g
[
i
]
[
0
]
=
s
i
g
a
m
(
m
a
x
(
f
[
s
o
n
]
[
0
]
,
f
[
s
o
n
]
[
1
]
)
)
(
并
且
s
o
n
不
是
i
节
点
的
重
儿
子
)
g[i][0] = sigam(max(f[son][0] , f[son][1]))(并且son不是i节点的重儿子)
g[i][0]=sigam(max(f[son][0],f[son][1]))(并且son不是i节点的重儿子)
g
[
i
]
[
1
]
=
s
i
g
a
m
(
f
[
s
o
n
]
[
0
]
)
(
并
且
s
o
n
不
是
i
节
点
的
重
儿
子
)
g[i][1] = sigam(f[son][0])(并且son不是i节点的重儿子)
g[i][1]=sigam(f[son][0])(并且son不是i节点的重儿子)
F
[
i
]
[
0
/
1
]
:
F[i][0/1]:
F[i][0/1]:以i节点为根的子树,选/不选i节点的最大权独立集
F
[
i
]
[
0
]
=
g
[
i
]
[
0
]
+
m
a
x
(
f
[
c
h
[
n
o
w
]
[
0
]
]
,
f
[
c
h
[
n
o
w
]
[
1
]
]
)
F[i][0] = g[i][0] + max(f[ch[now][0]] , f[ch[now][1]])
F[i][0]=g[i][0]+max(f[ch[now][0]],f[ch[now][1]])
F
[
i
]
[
1
]
=
v
a
l
[
i
]
+
g
[
i
]
[
1
]
+
f
[
c
h
[
n
o
w
]
]
[
0
]
F[i][1] = val[i] + g[i][1] + f[ch[now]][0]
F[i][1]=val[i]+g[i][1]+f[ch[now]][0]
然后将上面式子 写成矩阵乘法形式(方便书写)
[
g
[
i
]
[
0
]
g
[
i
]
[
0
]
g
[
i
]
[
1
]
+
v
a
l
[
i
]
−
i
n
f
]
∗
[
f
[
c
h
[
n
o
w
]
]
[
0
]
f
[
c
h
[
n
o
w
]
]
[
1
]
]
=
\left[ \begin{matrix} g[i][0] & g[i][0] \\ g[i][1] + val[i] & -inf \end{matrix} \right] * \left[ \begin{matrix} f[ch[now]][0] \\ f[ch[now]][1] \end{matrix} \right]=
[g[i][0]g[i][1]+val[i]g[i][0]−inf]∗[f[ch[now]][0]f[ch[now]][1]]=
[
f
[
i
]
[
0
]
f
[
i
]
[
1
]
]
\left[ \begin{matrix} f[i][0] \\ f[i][1] \end{matrix} \right]
[f[i][0]f[i][1]]
然后发现可以将上面的那个方程一直递归下去。。。。(恰好是链底到链顶)
然后就可以优美的解决查询问题
考虑修改
考虑修改对应节点的g矩阵时,会对当前节点所处链顶节点的父亲的g矩阵影响
再修改,在往上。。直至修改到1为止
综上
这个黑 紫题就被这么愉快的解决了
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
int n,m,a[MAXN],tot,h[MAXN];
int sz[MAXN],ch[MAXN],dep[MAXN],f[MAXN],yxx[MAXN][2],g[MAXN][2];
int dex,dfn[MAXN],id[MAXN],tp[MAXN],maxl[4];
int last[MAXN];
struct node{
int from,to,next;
}e[MAXN << 1];
struct Ma{
int a[2][2];
void init(){
a[0][0] = a[0][1] = a[1][0] = a[1][1] = 0;
return;
}
}t[MAXN * 8];
Ma operator * (Ma x , Ma y){
Ma z;
z.a[0][0] = max(x.a[0][0] + y.a[0][0] , x.a[0][1] + y.a[1][0]);
z.a[0][1] = max(x.a[0][0] + y.a[0][1] , x.a[0][1] + y.a[1][1]);
z.a[1][0] = max(x.a[1][0] + y.a[0][0] , x.a[1][1] + y.a[1][0]);
z.a[1][1] = max(x.a[1][0] + y.a[0][1] , x.a[1][1] + y.a[1][1]);
return z;
}
void add(int x , int y){
tot++;
e[tot].from = x;
e[tot].to = y;
e[tot].next = h[x];
h[x] = tot;
}
void dfs(int now , int fa){
yxx[now][1] = a[now] , yxx[now][0] = 0;
f[now] = fa , dep[now] = dep[fa] + 1 , sz[now] = 1;
for(int i = h[now] ; i != (-1) ; i = e[i].next){
if(e[i].to == fa)continue;
dfs(e[i].to , now);sz[now] = sz[now] + sz[e[i].to];
if(sz[ch[now]] < sz[e[i].to])ch[now] = e[i].to;
yxx[now][0] = yxx[now][0] + max(yxx[e[i].to][0] , yxx[e[i].to][1]);
yxx[now][1] = yxx[now][1] + yxx[e[i].to][0];
}
}
void dfs2(int now , int fa){
dfn[now] = ++dex;
last[tp[now]] = dex;
id[dex] = now;
g[now][1] = a[now];
if(ch[now]){
tp[ch[now]] = tp[now];
dfs2(ch[now] , now);
}
for(int i = h[now] ; i != (-1) ; i = e[i].next){
if(e[i].to == fa || e[i].to == ch[now])continue;
tp[e[i].to] = e[i].to;
dfs2(e[i].to , now);
g[now][0] = g[now][0] + max(yxx[e[i].to][0] , yxx[e[i].to][1]);
g[now][1] = g[now][1] + yxx[e[i].to][0];
}
}
void build(int rt , int l , int r){
if(l == r){
t[rt].a[0][0] = g[id[l]][0];
t[rt].a[1][0] = g[id[l]][0];
t[rt].a[1][1] = -99999999;
t[rt].a[0][1] = g[id[l]][1];
return;
}
int mid = (l + r) >> 1;
build(rt << 1 , l , mid);
build((rt << 1) | 1 , mid + 1 , r);
t[rt] = t[rt << 1] * t[(rt << 1) | 1];
return;
}
void update(int rt , int l , int r , int x){
if(r < x || l > x)return;
if(l == r){
t[rt].a[0][0] = g[id[l]][0];
t[rt].a[1][0] = g[id[l]][0];
t[rt].a[1][1] = -99999999;
t[rt].a[0][1] = g[id[l]][1];
return;
}
int mid = (l + r) >> 1;
update(rt << 1 , l , mid , x);
update((rt << 1) | 1 , mid + 1 , r , x);
t[rt] = t[rt << 1] * t[(rt << 1) | 1];
return;
}
Ma que(int rt , int l , int r , int x , int y){
if(x <= l && r <= y)return t[rt];
int mid = (l + r) >> 1;
if(mid >= y)return que(rt << 1 , l , mid , x , y);
if(mid < x)return que((rt << 1) | 1 , mid + 1 , r , x , y);
return que(rt << 1 , l , mid , x , y) * que((rt << 1) | 1 , mid + 1 , r , x , y);
}
void out(){
Ma zz = que(1 , 1 , n , dfn[1] , last[1]);
maxl[0] = max(zz.a[0][0] , zz.a[0][1]);
maxl[1] = max(zz.a[1][0] , zz.a[1][1]);
cout<<max(maxl[0] , maxl[1])<<endl;
}
void sp_update(int x , int y){
int zz;
Ma zz1 , zz2;
g[x][1] = g[x][1] - a[x] + y , a[x] = y;
while(tp[x] != 1){
zz1 = que(1 , 1 , n , dfn[tp[x]] , last[tp[x]]);
update(1 , 1 , n , dfn[x]);
zz2 = que(1 , 1 , n , dfn[tp[x]] , last[tp[x]]);
x = f[tp[x]];
zz = max(zz1.a[0][0] , zz1.a[0][1]) - max(zz2.a[0][0] , zz2.a[0][1]);
g[x][0] = g[x][0] - zz;
zz = max(zz1.a[1][0] , zz1.a[1][1]) - max(zz2.a[1][0] , zz2.a[1][1]);
g[x][1] = g[x][1] - zz;
}
update(1 , 1 , n , dfn[x]);
out();
}
void init(){
memset(h , -1 , sizeof(h));
tot = dex = 0;tp[1] = 1;
cin>>n>>m;int x,y;
for(int i = 1 ; i <= n ; i++)cin>>a[i];
for(int i = 1 ; i < n ; i++){
cin>>x>>y;
add(x , y) , add(y , x);
}
dfs(1 , 1);
dfs2(1 , 1);
build(1 , 1 , n);
}
void solve(){
//for(int i = 1 ; i <= n ; i++)cout<<" "<<i<<" "<<g[i][0]<<" "<<g[i][1]<<endl;
int x,y;
while(m--){
cin>>x>>y;
sp_update(x , y);
}
}
int main(){
init();
solve();
}