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分
Luogu 4751 动态DP 模板的更多相关文章
- 【洛谷P4719】动态dp 动态dp模板
题目大意:给你一颗$n$个点的树,点有点权,有$m$次操作,每次操作给定$x$,$y$,表示修改点$x$的权值为$y$. 你需要在每次操作之后求出这棵树的最大权独立集的权值大小. 数据范围:$n,m≤ ...
- Luogu P4643 【模板】动态dp
题目链接 Luogu P4643 题解 猫锟在WC2018讲的黑科技--动态DP,就是一个画风正常的DP问题再加上一个动态修改操作,就像这道题一样.(这道题也是PPT中的例题) 动态DP的一个套路是把 ...
- LG4719 【模板】动态dp 及 LG4751 动态dp【加强版】
题意 题目描述 给定一棵\(n\)个点的树,点带点权. 有\(m\)次操作,每次操作给定\(x,y\),表示修改点\(x\)的权值为\(y\). 你需要在每次操作之后求出这棵树的最大权独立集的权值大小 ...
- 洛谷4719 【模板】动态dp
题目:https://www.luogu.org/problemnew/show/P4719 关于动态DP似乎有猫锟的WC2018论文,但找不见:还是算了. http://immortalco.blo ...
- 洛谷P4719 【模板】"动态 DP"&动态树分治
[模板]"动态 DP"&动态树分治 第一道动态\(DP\)的题,只会用树剖来做,全局平衡二叉树什么的就以后再学吧 所谓动态\(DP\),就是在原本的\(DP\)求解的问题上 ...
- 【模板】动态 DP
luogu传送门. 最近学了一下动态dp,感觉没有想象的难. 动态DP simple的DP是这样的: 给棵树,每个点给个权值,求一下最大权独立集. 动态DP是这样的: 给棵树,每个点给个权值还到处改, ...
- 洛谷P4719 【模板】动态dp(ddp LCT)
题意 题目链接 Sol 动态dp板子题.有些细节还没搞懂,待我研究明白后再补题解... #include<bits/stdc++.h> #define LL long long using ...
- 【洛谷】P4643 【模板】动态dp
题解 在冬令营上听到冬眠的东西,现在都是板子了猫锟真的是好毒瘤啊(雾) (立个flag,我去thusc之前要把WC2018T1乱搞过去= =) 好的,我们可以参考猫锟的动态动态dp的课件,然后你发现你 ...
- 「LGP4719【模板】动态dp」
题目 尽管知道这个东西应该不会考了,但是还是学一学吧 哎要是去年noip之前学该多好 动态\(dp\)就是允许修改的一个\(dp\),比如这道题,我们都知道这是一个树上最大点权独立集 众所周知方程长这 ...
随机推荐
- 创建线程的三种方式(Thread、Runnable、Callable)
方式一:继承Thread类实现多线程: 1. 在Java中负责实现线程功能的类是java.lang.Thread 类. 2. 可以通过创建 Thread的实例来创建新的线程. 3. 每个线程都是通过某 ...
- Ubuntu 18.04 LTS 设置代理(系统代理;http 代理;sock5 代理;apt 代理 ...)
1. 设置系统代理 1.1 设置 http 代理 1.1.1 只在当前 shell 生效 export http_proxy="http://<user>:<passwor ...
- 题解 Luogu P1110 【[ZJOI2007]报表统计】
感谢 @cmy962085349 提供的hack数据,已经改对了. 先声明,我好像是题解里写双$fhq$ $treap$里唯一能过的...(最后两个点啊) 思路:首先看题目,$MIN_GAP_SORT ...
- 剑指offer28:找出数组中超过一半的数字。
1 题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出 ...
- 简单layer 快速上手
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 面试题之web访问突然延迟问题
前言 面试官经常会问平时访问正常的网页突然变慢是什么原因引起的,说明下你排查的思路:我认为这种问题很能考察一个人的综合知识面,既能融通的贯彻知识点,也能展看对每个知识点进行详细的考问. 下面我按我自己 ...
- go guid 和uuid生成
1 安装 开始-运行 输入 cmd 回车 输入 go get -u github.com/typa01/go-utils 安装完毕后 2 使用 a 首先引入包 import ( goutil ...
- Linux 常见压缩格式详解
linux 文件压缩格式详解 压缩文件原理 在计算机科学和信息论中,数据压缩或者源编码是按照特定的编码机制用比未经编码少的数据比特(或者其它信息相关的单位)表示信息的过程.例如,如果我们将" ...
- angular.module 详解
AngularJS 模块 模块包含了主要的应用代码. 一个应用可以包含多个模块,每一个模块都包含了定义具体功能的代码. 可以将module理解成一个容器,可以往其中放入controllers.serv ...
- Interval 用法总结
语法:INTERVAL 'integer [- integer]' {YEAR | MONTH} [(precision)][TO {YEAR | MONTH}] 该数据类型常用来表示一段时间差, 注 ...