题目描述
给定一棵nnn个点的树,点带点权。
有mmm次操作,每次操作给定x,yx,yx,y,表示修改点xxx的权值为yyy。
你需要在每次操作之后求出这棵树的最大权独立集的权值大小。
输入格式
第一行,n,mn,mn,m,分别代表点数和操作数。
第二行,V1,V2,…,VnV_1,V_2,…,V_nV1,V2,…,Vn,代表nnn个点的权值。
接下来n−1n-1n−1行,x,yx,yx,y,描述这棵树的n−1n-1n−1条边。
接下来mmm行,x,yx,yx,y,修改点xxx的权值为yyy。
输出格式
对于每个操作输出一行一个整数,代表这次操作后的树上最大权独立集。
保证答案在intintint范围内
输入输出样例
输入 #1
10 10
-11 80 -99 -76 56 38 92 -51 -34 47
2 1
3 1
4 3
5 2
6 2
7 1
8 2
9 4
10 7
9 -44
2 -17
2 98
7 -58
8 48
3 99
8 -61
9 76
9 14
10 93
输出 #1
186
186
190
145
189
288
244
320
258
304
说明/提示
对于30%的数据,1≤n,m≤101\le n,m\le 101≤n,m≤10
对于60%的数据,1≤n,m≤10001\le n,m\le 10001≤n,m≤1000
对于100%的数据,1≤n,m≤1051\le n,m\le 10^51≤n,m≤105
积累模板
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#define N 100005
using namespace std;
int head[N],ver[N<<1],nex[N<<1];
int tot,n,m,dfn[N],id[N],size[N],top[N],end[N],dfs_num,wson[N],a[N],fa[N];
struct Maxtrix{
int a[2][2];
Maxtrix(){
memset(a,0xcf,sizeof(a));
}
}val[N];
Maxtrix operator *(Maxtrix x,Maxtrix y){
Maxtrix res;
for(int i=0;i<2;++i){
for(int j=0;j<2;++j){
for(int k=0;k<2;++k){
res.a[i][j]=max(res.a[i][j],x.a[i][k]+y.a[k][j]);
}
}
}
return res;
}
inline void add(int x,int y){
nex[++tot]=head[x];head[x]=tot;ver[tot]=y;
}
struct segment{
int l[N<<2],r[N<<2];
Maxtrix M[N<<2];
void push_up(int p){
M[p]=M[p<<1]*M[p<<1|1];
}
void build(int p,int left,int right){
l[p]=left;r[p]=right;
if(left==right){
M[p]=val[id[left]];
// cout<<p<<" "<<id[left]<<endl;
return ;
}
int mid=(left+right)>>1;
build(p<<1,left,mid);build(p<<1|1,mid+1,right);
push_up(p);
}
void update_tree(int p,int left){
if(l[p]==r[p]){
//out(p);
M[p]=val[id[left]];//cout<<p<<endl;
return ;
}
int mid=(l[p]+r[p])>>1;
if(left<=mid)update_tree(p<<1,left);
else update_tree(p<<1|1,left);
push_up(p);
}
Maxtrix query(int p,int left,int right){
if(l[p]==left&&r[p]==right){
return M[p];
}
int mid=(l[p]+r[p])>>1;
if(right<=mid)return query(p<<1,left,right);
if(left>mid)return query(p<<1|1,left,right);
return query(p<<1,left,mid)*query(p<<1|1,mid+1,right);
}
void out(int p){
cout<<l[p]<<"->"<<r[p]<<endl;
for(int i=0;i<2;++i){
for(int j=0;j<2;++j){
cout<<M[p].a[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
}
}T;
void dfs1(int x,int las){
size[x]=1;int max_size=0;
//cout<<x<<endl;
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==las)continue;
fa[y]=x;
dfs1(y,x);
if(size[y]>max_size)max_size=size[y],wson[x]=y;
size[x]+=size[y];
}
}
int f[N][2];
void dfs2(int x,int las,int chain){
dfn[x]=++dfs_num;id[dfs_num]=x;
top[x]=chain;end[chain]=max(end[chain],dfn[x]);
f[x][0]=0;f[x][1]=a[x];
val[x].a[0][0]=val[x].a[0][1]=0;
val[x].a[1][0]=a[x];
if(wson[x]){
dfs2(wson[x],x,chain);
f[x][0]+=max(f[wson[x]][0],f[wson[x]][1]);
f[x][1]+=f[wson[x]][0];
}
for(int i=head[x];i;i=nex[i]){
int y=ver[i];
if(y==las||wson[x]==y)continue;
dfs2(y,x,y);
f[x][0]+=max(f[y][0],f[y][1]);
f[x][1]+=f[y][0];
val[x].a[0][0]+=max(f[y][0],f[y][1]);
val[x].a[0][1]=val[x].a[0][0];
val[x].a[1][0]+=f[y][0];
}
}
void update(int u,int w){
val[u].a[1][0]+=w-a[u];
a[u]=w;
Maxtrix pre,suf;
// cout<<":"<<endl;
while(u){
pre=T.query(1,dfn[top[u]],end[top[u]]);
T.update_tree(1,dfn[u]);//cout<<u<<" "<<dfn[u]<<endl;
suf=T.query(1,dfn[top[u]],end[top[u]]);
u=fa[top[u]];
val[u].a[0][0]+=max(suf.a[0][0],suf.a[1][0])-max(pre.a[0][0],pre.a[1][0]);
val[u].a[0][1]=val[u].a[0][0];
val[u].a[1][0]+=suf.a[0][0]-pre.a[0][0];
}
}
void test(){
for(int i=1;i<=n;++i){
for(int j=0;j<2;++j){
for(int k=0;k<2;++k){
cout<<val[i].a[j][k]<<" ";
}
cout<<endl;
}
cout<<endl;
}
cout<<endl;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)scanf("%d",&a[i]);
for(int i=1;i<n;++i){
int x,y;scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
dfs1(1,0);
dfs2(1,0,1);
//test();
T.build(1,1,n);
/* for(int i=1;i<=n*4;++i){
T.out(i);
}*/
for(int i=1;i<=m;++i){
int u,w;scanf("%d%d",&u,&w);
update(u,w);
Maxtrix ans=T.query(1,dfn[1],end[1]);
//cout<<dfn[1]<<" "<<end[1]<<endl;
printf("%d\n",max(ans.a[0][0],ans.a[1][0]));
}
return 0;
}
/*
10 10
-11 80 -99 -76 56 38 92 -51 -34 47
2 1
3 1
4 3
5 2
6 2
7 1
8 2
9 4
10 7
9 -44
2 -17
2 98
7 -58
8 48
3 99
8 -61
9 76
9 14
10 93
*/