bzoj5210(动态DP)

题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=5210

题解

依旧先树链剖分

设 $dp[i][0]$ 为取 $i$ 的最大联通块,$dp[i][1]$ 为 $i$ 为子树的最大联通块

$dp[i][0]=a[i]+\sum max{0,dp[son][0] }$

$dp[i][1]=max_j {dp[j][0] }$

设 $g$ 为不考虑重链的情况,那么

然后直接查询直接求矩阵乘积

那么修改需要考虑自身作为轻儿子的影响,而 $g[i][1]$ 是直接取 $max$ 的,所以可以直接在每个节点开 $set$ 维护轻儿子,然后复杂度依旧是 $O(nlogn)​$,然后发现跑得贼慢。。原因是矩阵乘法太费时了。。可以换成普通的转移做。。




代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

/**
*         ┏┓    ┏┓
*         ┏┛┗━━━━━━━┛┗━━━┓
*         ┃       ┃  
*         ┃   ━    ┃
*         ┃ >   < ┃
*         ┃       ┃
*         ┃... ⌒ ...  ┃
*         ┃ ┃
*         ┗━┓ ┏━┛
*          ┃ ┃ Code is far away from bug with the animal protecting          
*          ┃ ┃ 神兽保佑,代码无bug
*          ┃ ┃           
*          ┃ ┃       
*          ┃ ┃
*          ┃ ┃           
*          ┃ ┗━━━┓
*          ┃ ┣┓
*          ┃ ┏┛
*          ┗┓┓┏━━━━━━━━┳┓┏┛
*           ┃┫┫ ┃┫┫
*           ┗┻┛ ┗┻┛
*/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<set>
#include<bitset>
#include<assert.h>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-8
#define succ(x) (1<<x)
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid (x+y)/2
#define NM 200005
#define nm 400005
#define pi 3.1415926535897931
using namespace std;
const ll inf=1e18;
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}




struct edge{int t;edge*next;}e[nm],*h[NM],*o=e;
void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
int n,m,_x,_y;
ll g[NM][2],d[NM][2],a[NM];
int son[NM],c[NM],id[NM],tot,top[NM],TOP,f[NM],end[NM],size[NM];
char _s[5];
multiset<ll>p[NM];
multiset<ll>::iterator it;

void dfs1(int x){
d[x][0]=a[x];
link(x)if(j->t!=f[x]){
f[j->t]=x;
dfs1(j->t);
if(size[j->t]>size[son[x]])son[x]=j->t;
size[x]+=size[j->t];
d[x][0]+=max(d[j->t][0],0ll);
d[x][1]=max(d[x][1],d[j->t][1]);
}
size[x]++;d[x][1]=max(d[x][1],d[x][0]);
}
void dfs2(int x){
top[x]=TOP;id[x]=++tot;c[tot]=x;g[x][0]=a[x];end[x]=x;
if(son[x])dfs2(son[x]),end[x]=end[son[x]];
link(x)if(!top[j->t]){
dfs2(TOP=j->t);
g[x][0]+=max(d[j->t][0],0ll);
p[x].insert(d[j->t][1]);
}
if(p[x].empty()){g[x][1]=g[x][0];return;}
it=p[x].end();it--;
g[x][1]=max(*it,g[x][0]);
}

struct mat{int n,m;ll a[3][3];}one;
mat operator*(const mat&x,const mat&y){
mat s;s.n=x.n;s.m=y.m;inc(i,0,2)inc(j,0,2)s.a[i][j]=-inf;
inc(i,0,s.n)inc(k,0,x.m)if(x.a[i][k]>-inf)inc(j,0,s.m)if(y.a[k][j]>-inf)s.a[i][j]=max(s.a[i][j],x.a[i][k]+y.a[k][j]);
return s;
}

struct node{
node*l,*r;
int x,y;
mat s;
void upd(){s=l->s*r->s;}
node(int x,int y,node*l=0,node*r=0):x(x),y(y),l(l),r(r){
if(x==y){
mem(s.a);s.n=s.m=2;
s.a[0][1]=s.a[2][0]=s.a[2][1]=-inf;
s.a[0][0]=s.a[0][2]=s.a[1][0]=g[c[x]][0];s.a[1][2]=g[c[x]][1];
}else upd();
}
void mod(){
if(x==y){
s.a[0][0]=s.a[0][2]=s.a[1][0]=g[c[x]][0];s.a[1][2]=g[c[x]][1];
return;
}
if(_x<=mid)l->mod();else r->mod();upd();
}
mat sum(){
if(_x<=x&&y<=_y)return s;
if(_x>mid)return r->sum();
if(_y<=mid)return l->sum();
return l->sum()*r->sum();
}
}*root;
node*build(int x,int y){return x==y?new node(x,y):new node(x,y,build(x,mid),build(mid+1,y));}

void ch(int x){
g[x][0]+=_y-a[x];a[x]=_y;
if(!p[x].empty()){
it=p[x].end();it--;
g[x][1]=max(*it,g[x][0]);
}else g[x][1]=g[x][0];
_x=id[x];root->mod();
while(top[x]>1){
x=top[x];
_x=id[x];_y=id[end[x]];mat t=root->sum()*one;
g[f[x]][0]-=max(d[x][0],0ll)-max(t.a[0][0],0ll);
p[f[x]].erase(p[f[x]].lower_bound(d[x][1]));p[f[x]].insert(d[x][1]=t.a[1][0]);
it=p[f[x]].end();it--;
g[f[x]][1]=max(*it,g[f[x]][0]);
d[x][0]=max(t.a[0][0],0ll);
x=f[x];_x=id[x];root->mod();
}
}

int main(){
freopen("data.in","r",stdin);
n=read();m=read();
inc(i,1,n)a[i]=read();
inc(i,2,n){_x=read();_y=read();add(_x,_y);add(_y,_x);}
dfs1(f[1]=1);dfs2(TOP=1);
//inc(i,1,n)printf("%d ",top[i]);putchar('\n');
//inc(i,1,n)printf("%d ",end[i]);putchar('\n');
root=build(1,n);
one.n=2;one.m=0;
while(m--){
scanf("%s",_s);_x=read();
if(_s[0]=='M'){
_y=read();ch(_x);
}else{
_y=id[end[_x]];_x=id[_x];
mat ans=root->sum()*one;
printf("%lld\n",ans.a[1][0]);
}
}
return 0;
}