Luogu 4751 动态DP 模板
题面
动态求最大独立集
题解
树剖后用矩阵转移。
具体见Tweetuzki的洛谷博客
CODE
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
char cb[1<<15],*cs=cb,*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
inline void read(int &x) {
char ch; int flg=1; while(!isdigit(ch=getc()))if(ch=='-')flg=-flg;
for(x=ch-'0';isdigit(ch=getc());x=x*10+ch-'0'); x*=flg;
}
const int MAXN = 1000005;
const int INF = 1000000000;
int n, m, V[MAXN], fir[MAXN], nxt[MAXN<<1], to[MAXN<<1], cnt;
inline void link(int u, int v) {
to[++cnt] = v; nxt[cnt] = fir[u]; fir[u] = cnt;
to[++cnt] = u; nxt[cnt] = fir[v]; fir[v] = cnt;
}
int tmr, fa[MAXN], dfn[MAXN], tp[MAXN], bt[MAXN], son[MAXN], sz[MAXN], seq[MAXN];
struct mat {
int a[2][2];
int* operator[](int x) { return a[x]; }
mat operator*(const mat &o)const {
mat re;
for(int i = 0; i < 2; ++i)
for(int j = 0; j < 2; ++j)
re.a[i][j] = max(a[i][0]+o.a[0][j], a[i][1]+o.a[1][j]);
return re;
}
}t[MAXN<<2], val[MAXN];
void dfs1(int u, int ff) {
fa[u] = ff; sz[u] = 1;
for(int i = fir[u], v; i; i = nxt[i])
if((v=to[i]) != ff) {
dfs1(v, u), sz[u] += sz[v];
(sz[v] > sz[son[u]]) && (son[u] = v);
}
}
int f[MAXN][2];
void dfs2(int u, int top) {
tp[u] = top; bt[top] = u;
seq[dfn[u]=++tmr] = u;
if(son[u]) dfs2(son[u], top);
for(int i = fir[u], v; i; i = nxt[i])
if((v=to[i]) != fa[u] && v != son[u])
dfs2(v, v);
}
void dp(int u) {
f[u][0] = 0; f[u][1] = V[u];
for(int i = fir[u], v; i; i = nxt[i])
if((v=to[i]) != fa[u])
dp(v),
f[u][0] += max(f[v][0], f[v][1]),
f[u][1] += f[v][0];
}
void build(int i, int l, int r) {
if(l == r) {
int f0 = 0, f1 = V[seq[l]];
for(int j = fir[seq[l]], v; j; j = nxt[j])
if((v=to[j]) != fa[seq[l]] && v != son[seq[l]])
f0 += max(f[v][0], f[v][1]),
f1 += f[v][0];
val[l] = t[i] = (mat){ {{f0, f0} , {f1, -INF}} };
return;
}
int mid = (l + r) >> 1;
build(i<<1, l, mid);
build(i<<1|1, mid+1, r);
t[i] = t[i<<1] * t[i<<1|1];
}
void update(int i, int l, int r, int x) {
if(l == r) { t[i] = val[l]; return; }
int mid = (l + r) >> 1;
if(x <= mid) update(i<<1, l, mid, x);
else update(i<<1|1, mid+1, r, x);
t[i] = t[i<<1] * t[i<<1|1];
}
mat query(int i, int l, int r, int x, int y) {
if(x == l && r == y) return t[i];
int mid = (l + r) >> 1;
if(y <= mid) return query(i<<1, l, mid, x, y);
if(x > mid) return query(i<<1|1, mid+1, r, x, y);
return query(i<<1, l, mid, x, mid) * query(i<<1|1, mid+1, r, mid+1, y);
}
void modify(int u, int W) {
val[dfn[u]][1][0] += W-V[u]; V[u]=W;
while(u) {
mat pre = query(1, 1, n, dfn[tp[u]], dfn[bt[tp[u]]]);
update(1, 1, n, dfn[u]);
mat now = query(1, 1, n, dfn[tp[u]], dfn[bt[tp[u]]]);
u = fa[tp[u]]; if(!u) return; int x = dfn[u];
int p0 = pre[0][0], p1 = pre[1][0];
int n0 = now[0][0], n1 = now[1][0];
val[x][0][0] = val[x][0][1] = val[x][0][0] + max(n0, n1) - max(p0, p1);
val[x][1][0] = val[x][1][0] + n0 - p0;
}
}
int main () {
read(n), read(m);
for(int i = 1; i <= n; ++i) read(V[i]);
for(int i = 1, u, v; i < n; ++i) read(u), read(v), link(u, v);
dfs1(1, 0), dfs2(1, 1), dp(1);
build(1, 1, n);
int x, y, lstans=0;
while(m--) {
read(x), read(y); x^=lstans; modify(x, y);
mat ans = query(1, 1, n, 1, dfn[bt[1]]);
printf("%d\n", lstans=max(ans[0][0], ans[1][0]));
}
}
加强版只过80分