动态dp 板子
动态dp
瞎扯两句吧
先从序列上理解,维护链的最大独立集。
考虑是从左边转移的,那么矩阵的转移唯一,直接放在线段树上就可以了。
放在树上的话,儿子都可以转移,把轻儿子的转移放在子链链头更新,然后每条链都处理成序列就行了。
注意一点,因为维护的是序列,所以单点存放的矩阵是只含轻儿子和自己的贡献,相当于把轻儿子的子树缩给了自己,而重儿子维护的东西是通过线段树上维护的区间贡献过来的。
咕咕模板,最大全独立集
Code:
#include <cstdio>
#include <algorithm>
#include <cctype>
using std::max;
const int N=1e5+10;
const int inf=0x3f3f3f3f;
int n,m,v[N];
int read()
{
int x=0,f=1;char c=getchar();
while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
while(isdigit(c)) {x=x*10+c-'0';c=getchar();}
return x*f;
}
int head[N],to[N<<1],Next[N<<1],cnt;
void add(int u,int v)
{
to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
}
int dfn[N],top[N],bot[N],siz[N],ha[N],f[N],ws[N],dfsclock,dp[N][2],len;
void dfs1(int now)
{
++siz[now],dp[now][1]=v[now];
for(int v,i=head[now];i;i=Next[i])
if((v=to[i])!=f[now])
{
f[v]=now,dfs1(v),siz[now]+=siz[v];
dp[now][1]+=dp[v][0];
dp[now][0]+=max(dp[v][0],dp[v][1]);
if(siz[v]>siz[ws[now]]) ws[now]=v;
}
}
void dfs2(int now,int anc)
{
ha[dfn[now]=++dfsclock]=now;
bot[top[now]=anc]=now;
if(ws[now]) dfs2(ws[now],anc);
for(int v,i=head[now];i;i=Next[i])
if(!dfn[v=to[i]])
dfs2(v,v);
bot[now]=bot[anc];
}
struct matrix{int dx[2][2];}mx[N<<2],upt[N];
matrix operator *(matrix a,matrix b)
{
matrix ret;
ret.dx[0][0]=max(a.dx[0][0]+b.dx[0][0],a.dx[0][1]+b.dx[1][0]);
ret.dx[0][1]=max(a.dx[0][0]+b.dx[0][1],a.dx[0][1]+b.dx[1][1]);
ret.dx[1][0]=max(a.dx[1][0]+b.dx[0][0],a.dx[1][1]+b.dx[1][0]);
ret.dx[1][1]=max(a.dx[1][0]+b.dx[0][1],a.dx[1][1]+b.dx[1][1]);
return ret;
}
#define ls id<<1
#define rs id<<1|1
void build(int id,int l,int r)
{
if(l==r)
{
int now=ha[l],g0=0,g1=v[now];
for(int v,i=head[now];i;i=Next[i])
if((v=to[i])!=ws[now]&&v!=f[now])
g0+=max(dp[v][0],dp[v][1]),g1+=dp[v][0];
upt[l]=mx[id]=(matrix){g0,g0,g1,-inf};
return;
}
int mid=l+r>>1;
build(ls,l,mid),build(rs,mid+1,r);
mx[id]=mx[ls]*mx[rs];
}
matrix query(int id,int L,int R,int l,int r)
{
if(l==L&&r==R) return mx[id];
int Mid=L+R>>1;
if(r<=Mid) return query(ls,L,Mid,l,r);
else if(l>Mid) return query(rs,Mid+1,R,l,r);
else return query(ls,L,Mid,l,Mid)*query(rs,Mid+1,R,Mid+1,r);
}
void change(int id,int l,int r,int p)
{
if(l==r) {mx[id]=upt[l];return;}
int mid=l+r>>1;
if(p<=mid) change(ls,l,mid,p);
else change(rs,mid+1,r,p);
mx[id]=mx[ls]*mx[rs];
}
void modify(int now,int w)
{
upt[dfn[now]].dx[1][0]+=w-v[now],v[now]=w;
while(233)
{
matrix a=query(1,1,n,dfn[top[now]],dfn[bot[now]]);
change(1,1,n,dfn[now]);
matrix b=query(1,1,n,dfn[top[now]],dfn[bot[now]]);
now=f[top[now]];
if(!now) break;
upt[dfn[now]].dx[0][0]+=max(b.dx[0][0],b.dx[1][0])-max(a.dx[0][0],a.dx[1][0]);
upt[dfn[now]].dx[0][1]=upt[dfn[now]].dx[0][0];
upt[dfn[now]].dx[1][0]+=b.dx[0][0]-a.dx[0][0];
}
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++) v[i]=read();
for(int u,v,i=1;i<n;i++) u=read(),v=read(),add(u,v),add(v,u);
dfs1(1),dfs2(1,1),build(1,1,n);
for(int u,w,i=1;i<=m;i++)
{
u=read(),w=read();
modify(u,w);
matrix ans=query(1,1,n,1,dfn[bot[1]]);
printf("%d\n",max(ans.dx[0][0],ans.dx[1][0]));
}
return 0;
}
2019.1.2
动态dp 板子的更多相关文章
- 洛谷P4719 【模板】动态dp(ddp LCT)
题意 题目链接 Sol 动态dp板子题.有些细节还没搞懂,待我研究明白后再补题解... #include<bits/stdc++.h> #define LL long long using ...
- P4719 【模板】"动态 DP"&动态树分治
题目描述 给定一棵 n 个点的树,点带点权. 有 m 次操作,每次操作给定 x,y,表示修改点 x 的权值为 y. 你需要在每次操作之后求出这棵树的最大权独立集的权值大小. 输入格式 第一行有两个整数 ...
- 【模板】动态 DP
luogu传送门. 最近学了一下动态dp,感觉没有想象的难. 动态DP simple的DP是这样的: 给棵树,每个点给个权值,求一下最大权独立集. 动态DP是这样的: 给棵树,每个点给个权值还到处改, ...
- 4712: 洪水 基于链分治的动态DP
国际惯例的题面:看起来很神的样子......如果我说这是动态DP的板子题你敢信?基于链分治的动态DP?说人话,就是树链剖分线段树维护DP.既然是DP,那就先得有转移方程.我们令f[i]表示让i子树中的 ...
- 【洛谷】P4643 【模板】动态dp
题解 在冬令营上听到冬眠的东西,现在都是板子了猫锟真的是好毒瘤啊(雾) (立个flag,我去thusc之前要把WC2018T1乱搞过去= =) 好的,我们可以参考猫锟的动态动态dp的课件,然后你发现你 ...
- 「LGP4719【模板】动态dp」
题目 尽管知道这个东西应该不会考了,但是还是学一学吧 哎要是去年noip之前学该多好 动态\(dp\)就是允许修改的一个\(dp\),比如这道题,我们都知道这是一个树上最大点权独立集 众所周知方程长这 ...
- 洛谷 P4719 【模板】动态dp【动态dp】
是动态dp的板子 大致思想就是用g[u]来表示不包含重链转移的dp值,然后用线段树维护重链,这样线段树的根就相当于这条重链的top的真实dp值 每次修改的时候,修改x点会影响到x到根的真实dp值,但是 ...
- bzoj5210 最大连通子块和 动态 DP + 堆
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5210 题解 令 \(dp[x][0]\) 表示以 \(x\) 为根的子树中的包含 \(x\) ...
- 模版 动态 dp
模版 动态 dp 终于来写这个东西了.. LG 模版:给定 n 个点的数,点有点权, $ m $ 次修改点权,求修改完后这个树的最大独立集大小. 我们先来考虑朴素的最大独立集的 dp \[dp[u][ ...
随机推荐
- Exp7:网络欺诈防范
Exp7:网络欺诈防范 基础问题回答 通常在什么场景下容易受到DNS spoof攻击? 答:同一局域网下,以及各种公共网络. 在日常生活工作中如何防范以上两攻击方法? 答: 使用最新版本的DNS服务器 ...
- 20155220 Exp9 Web安全基础实践
Exp9 Web安全基础实践 实验过程 开启webgoat 输入java -jar webgoat-container-7.1-exec.jar,来运行webgoat 在浏览器输入localhost: ...
- 20155302《网络对抗》Exp3 免杀原理与实践
20155302<网络对抗>Exp3 免杀原理与实践 实验要求 1.正确使用msf编码器,msfvenom生成如jar之类的其他文件,veil-evasion,自己利用shellcode编 ...
- 20155323刘威良《网络对抗》Exp5 MSF基础应用
20155323刘威良<网络对抗>Exp5 MSF基础应用 实践内容 本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路.具体需要完成: 1.1一个主动攻击实 ...
- 汇编 EAX,EBX,ECX,EDX,寄存器
知识点: 寄存器EAX 寄存器AX 寄存器AH 寄存器AL 一.EAX与AX,AH,AL关系图 一格表示一字节 #include <Windows.h> int _tmain(int ar ...
- 一步一步来熟悉Akka.Net(一)
一步一步来熟悉Akka.Net(一) 标签(空格分隔): .netcore 分布式 一.不利flag 好久没写过文章了,翻开前几年写的博客,看到有两个目标"代码生成器"和&qu ...
- NodeMCU学习(四):与其他设备通信
TCP连接 TCP是计算机网络中运输层协议,是应用层协议http协议的支撑协议.两台远程主机之间可以通过TCP/UDP协议进行通信并交换信息,前提是,相互通信的两台主机之间必须知道彼此的IP地址和端口 ...
- CM005-逆向分析过程(上篇)
前言 005,都说比较变态,很多人给放过去了,但是我还是决定上了它,既然变态就分两篇,上篇先实际说流程,到底应该怎么上它,下篇会告诉逆向分析的过程和方法 准备 [环境和工具] win7/xp虚拟机环境 ...
- 做游戏的小伙伴们注意了,DDoS还可以这样破!
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯游戏云发表于云+社区专栏 作者:腾讯DDoS安全专家.腾讯云游戏安全专家haroldchen 摘要:在游戏出海的过程中,DDoS攻 ...
- Unity3d Transform.forward和Vector3.forward的区别!
在Unity中有两个forward,一个是Transform.forward一个是Vector3.forward. 对于Vector3来说,它只是缩写.没有其它任何含义. Vector3.forwar ...