动态最大带权独立集
(还有一个是全局平衡二叉树的解法,还没学)
#include"bits/stdc++.h"
using namespace std;
const int inf = 1e8;
int n,m;
int v[100005];
const int nn = 1e5+10;
int link[nn<<1],son[nn<<1],nxt[nn<<1];
int tot_;
int top[nn],deep[nn],wson[nn],fa[nn],size[nn],bot[nn];
int f[nn][2];
int dfn[nn];
int id[nn];
int tot;
struct Mat
{
int l,r,a[3][3];
Mat(int a1=0,int a2=0,int d1=0,int d2=0,int d3=0,int d4=0)
{
l=a1,r=a2;
a[1][1]=d1,a[1][2] = d2;
a[2][1] = d3,a[2][2] = d4;
}
}tr[nn<<2];
Mat operator*(const Mat a,const Mat b)
{
Mat re=Mat(2,2);
re.a[1][1] = max(a.a[1][1]+b.a[1][1],a.a[1][2]+b.a[2][1]);
re.a[1][2] = max(a.a[1][1]+b.a[1][2],a.a[1][2]+b.a[2][2]);
re.a[2][1] = max(a.a[2][1]+b.a[1][1],a.a[2][2]+b.a[2][1]);
re.a[2][2] = max(a.a[2][1]+b.a[1][2],a.a[2][2]+b.a[2][2]); // 手动
return re;
}
inline int rd(){
int x=0;char c=getchar();int neg=1;
while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*neg;
}
inline void adde(int x,int y)
{
++tot_;
nxt[tot_] = link[x];
link[x] = tot_;
son[tot_] = y;
}
void dfs1(int x,int ff,int dd)
{
fa[x] =ff;
size[x] =1;
f[x][1] = v[x];
f[x][0] = 0;
for (int i=link[x];i;i=nxt[i])
{
int so = son[i];
if (so==ff) continue;
dfs1(so,x,dd+1);
size[x] += size[so];
if (size[wson[x]]<size[so]) wson[x] = so;
f[x][1] += f[so][0];
f[x][0] += max(f[so][1],f[so][0]);
}
}
void dfs2(int x,int t)
{
top[x] = t;
dfn[x] = ++tot;
id[tot] =x;
if (!wson[x]) bot[top[x]] = x;//不要写成t
else dfs2(wson[x],t);
for ( int i=link[x];i;i=nxt[i])
{
int so =son[i];
if (so==wson[x]||so==fa[x]) continue;
dfs2(so,so);
}
}
inline void change(int rt,int l,int r,int pos,int a,int b)
{
if (l==r)
{
tr[rt].a[1][1]+=a; tr[rt].a[2][1]+=a;
tr[rt].a[1][2]+=b;
return ;
}
int mid = l+r>>1;
if (pos<=mid) change(rt<<1,l,mid,pos,a,b);
else change(rt<<1|1,mid+1,r,pos,a,b);
tr[rt]=tr[rt<<1|1]*tr[rt<<1];//注意顺序
}
inline Mat query(int p,int l,int r,int x,int y){
if(x<=l&&r<=y)
{
return tr[p];
}
else{
int m=l+r>>1;Mat re=Mat(2,2,0,-inf,-inf,0);
if(y>=m+1) re=re*query(p<<1|1,m+1,r,x,y);
if(x<=m) re=re*query(p<<1,l,m,x,y);
return re;
}
}
inline void update(int x,int y)
{
Mat nw,od;
int a,b;
while (x)
{ if (y) a=0,b=y,y=0;
else a=max(nw.a[1][2],nw.a[1][1]) - max(od.a[1][2],od.a[1][1]),
b = nw.a[1][1] - od.a[1][1];
od = query(1,1,n,dfn[top[x]],dfn[bot[top[x]]]);
change(1,1,n,dfn[x],a,b);
nw = query(1,1,n,dfn[top[x]],dfn[bot[top[x]]]);
x=fa[top[x]];
}
printf("%d\n",max(nw.a[1][1],nw.a[1][2]));
}
void build (int rt,int l,int r)
{
if (l==r)
{
int zhi = id[l];
int a = f[zhi][0] - max(f[wson[zhi]][0],f[wson[zhi]][1]);
int b = f[zhi][1] - f[wson[zhi]][0];
tr[rt] = Mat(2,2,a,b,a,-1e8);
return ;
}
int mid = l+r>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
tr[rt]=tr[rt<<1|1]*tr[rt<<1];
}
int main()
{
n=rd(); m = rd();
for ( int i=1;i<=n;i++) v[i] = rd();
for ( int i =1;i<n;i++)
{
int a,b;a=rd(); b = rd();
adde(a,b);
adde(b,a);
}
dfs1(1,0,1);
dfs2(1,1);
build(1,1,n);
//puts("$%^&*");
for ( int i=1;i<=m;i++)
{
// puts("123f");
int a,b;a=rd(); b=rd();
update(a,b-v[a]);
// puts("213");
v[a] =b;
}
return 0;
}