动态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][ ...
随机推荐
- MySQL学习笔记04 插入中文时出现ERROR 1366 (HY000)
1 环境: MySQL Server 6.0 命令行工具 2 问题 : 插入中文字符数据出现如下错误: ERROR 1366 (HY000): Incorrect string value: '\ ...
- OWASP移动安全漏洞Top 10
•脆弱的服务器端安全控制 在OWASP排第一的漏洞是“脆弱的服务器端安全控制”,顾名思义,就是没有以一个安全的方式从移动应用程序向服务器端发送数据,或在发送数据时暴露了一些敏感的API.例如,考虑对一 ...
- pandas 索引与列相互转化
1. 准备数据 import pandas as pd from io import StringIO csv_txt = '''"date","player1" ...
- cocos2d-x学习记录1——图片显示
这篇算是cocos2d-x入门篇,显示一张图片即可. 观察工程中HelloWorld的结构,包含AppDelegate和HelloWorldScene两个类文件,AppDelegate中包含基本的处理 ...
- python3获取文件及文件夹大小
获取文件大小 os.path.getsize(file_path):file_path为文件路径 >>> import os >>> os.path.getsize ...
- BugkuCTF web2
前言 写了这么久的web题,算是把它基础部分都刷完了一遍,以下的几天将持续更新BugkuCTF WEB部分的题解,为了不影响阅读,所以每道题的题解都以单独一篇文章的形式发表,感谢大家一直以来的支持和理 ...
- Salesforce随笔: 将Visualforce Page渲染为PDF文件(Render a Visualforce Page as a PDF File)
参照 : Visualforce Developer Guide 第60页 <Render a Visualforce Page as a PDF File> 你可以用PDF渲染服务生成一 ...
- Verilog HDL数组(存储器)操作
本文从本人的163博客搬迁至此. 引用了http://blog.sina.com.cn/s/blog_9424755f0101rhrh.html Verilog HDL中常采用数组方式来对存储器进行建 ...
- PowerDesigner数据库设计实用技巧
欢迎大家补充,谢谢! 1. 原始单据与实体之间的关系 可以是一对一.一对多.多对多的关系.在一般情况下,它们是一对一的关系:即一张原始单据对应且只对应一个实体.在特殊情况下,它们可能是一对多或多对一的 ...
- Fragment 使用总结
1. 要深刻理解Fragment 的生命周期 2. Fragment.getActivity()并不能保证非空. 3.如果在Fragment中有异步的回调, 特别要注意此时Fragment 是否还at ...