题解:
日常的写不动题,存板
假设这玩意不是动态的:
设
f
[
i
]
[
0
/
1
]
f[i][0/1]
f[i][0/1]为第i个点不选/选的答案。那么
f
[
i
]
[
0
]
=
∑
max
(
f
[
j
]
[
0
]
,
f
[
j
]
[
1
]
)
,
f
[
i
]
[
1
]
=
∑
f
[
j
]
[
0
]
+
v
[
i
]
.
f[i][0]=\sum\max(f[j][0],f[j][1]),f[i][1]=\sum f[j][0]+v[i].
f[i][0]=∑max(f[j][0],f[j][1]),f[i][1]=∑f[j][0]+v[i].
然后修改一个点的权值最多对上面的值有影响。
然后再设
g
[
i
]
[
0
/
1
]
g[i][0/1]
g[i][0/1]为只考虑轻儿子的dp值。
于是
f
[
i
]
[
0
]
=
max
(
f
[
s
o
n
]
[
0
]
,
f
[
s
o
n
]
[
1
]
)
+
g
[
i
]
[
0
]
,
f
[
i
]
[
1
]
=
f
[
s
o
n
]
[
0
]
+
g
[
i
]
[
1
]
.
f[i][0]=\max(f[son][0],f[son][1])+g[i][0],f[i][1]=f[son][0]+g[i][1].
f[i][0]=max(f[son][0],f[son][1])+g[i][0],f[i][1]=f[son][0]+g[i][1].
然后利用人类智慧可以定义乘法为加法,定义加法为取max,搞出一个矩阵:
(
f
[
i
]
[
0
]
f
[
i
]
[
1
]
)
=
(
g
[
i
]
[
0
]
g
[
i
]
[
0
]
g
[
i
]
[
1
]
−
∞
)
×
(
f
[
s
o
n
]
[
0
]
f
[
s
o
n
]
[
1
]
)
\begin{pmatrix} f[i][0] \\ f[i][1] \end{pmatrix}=\begin{pmatrix} g[i][0] & g[i][0] \\ g[i][1] & -\infty \end{pmatrix}\times \begin{pmatrix} f[son][0] \\ f[son][1] \end{pmatrix}
(f[i][0]f[i][1])=(g[i][0]g[i][1]g[i][0]−∞)×(f[son][0]f[son][1])
然后就可以树剖再上个线段树维护了。修改的时候改改重链f值改改链顶g值就行了。
不知道为毛这道题右下角取0都能过
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100005
using namespace std;
int n,m,a[maxn],dep[maxn],fa[maxn],top[maxn],son[maxn],siz[maxn],tid[maxn],ed[maxn],rnk[maxn],ccnt,g[maxn][2];
struct node { int v; node *nxt; } edge[maxn*2],*head[maxn],*ncnt;
struct mat { int f[2][2]; } tree[maxn*4],val[maxn];
mat operator * (mat a,mat b)
{
mat c;
memset(c.f,0,sizeof(c.f));
for(int k=0;k<2;k++)
for(int i=0;i<2;i++)
for(int j=0;j<2;j++) c.f[i][j]=max(c.f[i][j],a.f[i][k]+b.f[k][j]);
return c;
}
void addedge(int u,int v)
{
ncnt++;
ncnt->v=v,ncnt->nxt=head[u];
head[u]=ncnt;
}
void dfs1(int u,int f,int d)
{
dep[u]=d,fa[u]=f,siz[u]=1,g[u][1]=a[u];
for(node *p=head[u];p;p=p->nxt)
{
int v=p->v;
if(v==f) continue;
dfs1(v,u,d+1); siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
g[u][0]+=max(g[v][0],g[v][1]),g[u][1]+=g[v][0];
}
}
void dfs2(int u,int tp)
{
tid[u]=++ccnt,rnk[ccnt]=u,top[u]=tp;
if(!son[u]) { ed[u]=u; return; }
dfs2(son[u],tp); ed[u]=ed[son[u]];
for(node *p=head[u];p;p=p->nxt)
{
int v=p->v;
if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
}
void Build(int i,int l,int r)
{
if(l==r)
{
int u=rnk[l],g0=0,g1=a[u];
for(node *p=head[u];p;p=p->nxt)
{
int v=p->v;
if(v!=fa[u]&&v!=son[u]) g0+=max(g[v][0],g[v][1]),g1+=g[v][0];
}
tree[i].f[0][0]=tree[i].f[0][1]=g0,tree[i].f[1][0]=g1;
val[l]=tree[i];
return;
}
int mid=(l+r)>>1;
Build(i<<1,l,mid); Build(i<<1|1,mid+1,r);
tree[i]=tree[i<<1]*tree[i<<1|1];
}
mat Query(int i,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr) return tree[i];
int mid=(l+r)>>1;
if(qr<=mid) return Query(i<<1,l,mid,ql,qr);
else if(ql>mid) return Query(i<<1|1,mid+1,r,ql,qr);
return Query(i<<1,l,mid,ql,qr)*Query(i<<1|1,mid+1,r,ql,qr);
}
void Modify(int i,int l,int r,int p)
{
if(l==r) { tree[i]=val[l]; return; }
int mid=(l+r)>>1;
if(p<=mid) Modify(i<<1,l,mid,p);
else Modify(i<<1|1,mid+1,r,p);
tree[i]=tree[i<<1]*tree[i<<1|1];
}
void Modify(int u,int x)
{
val[tid[u]].f[1][0]+=x-a[u]; a[u]=x;
while(u)
{
mat la=Query(1,1,n,tid[top[u]],tid[ed[u]]);
Modify(1,1,n,tid[u]);
mat cur=Query(1,1,n,tid[top[u]],tid[ed[u]]);
u=fa[top[u]];
val[tid[u]].f[0][0]+=max(cur.f[0][0],cur.f[1][0])-max(la.f[0][0],la.f[1][0]);
val[tid[u]].f[0][1]=val[tid[u]].f[0][0];
val[tid[u]].f[1][0]+=cur.f[0][0]-la.f[0][0];
}
}
int main()
{
scanf("%d%d",&n,&m); ncnt=&edge[0];
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v); addedge(v,u);
}
dfs1(1,0,1); dfs2(1,1);
Build(1,1,n);
while(m--)
{
int x,y;
scanf("%d%d",&x,&y);
Modify(x,y);
mat t=Query(1,1,n,tid[1],tid[ed[1]]);
printf("%d\n",max(t.f[0][0],t.f[1][0]));
}
}