动态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 板子的更多相关文章

  1. 洛谷P4719 【模板】动态dp(ddp LCT)

    题意 题目链接 Sol 动态dp板子题.有些细节还没搞懂,待我研究明白后再补题解... #include<bits/stdc++.h> #define LL long long using ...

  2. P4719 【模板】"动态 DP"&动态树分治

    题目描述 给定一棵 n 个点的树,点带点权. 有 m 次操作,每次操作给定 x,y,表示修改点 x 的权值为 y. 你需要在每次操作之后求出这棵树的最大权独立集的权值大小. 输入格式 第一行有两个整数 ...

  3. 【模板】动态 DP

    luogu传送门. 最近学了一下动态dp,感觉没有想象的难. 动态DP simple的DP是这样的: 给棵树,每个点给个权值,求一下最大权独立集. 动态DP是这样的: 给棵树,每个点给个权值还到处改, ...

  4. 4712: 洪水 基于链分治的动态DP

    国际惯例的题面:看起来很神的样子......如果我说这是动态DP的板子题你敢信?基于链分治的动态DP?说人话,就是树链剖分线段树维护DP.既然是DP,那就先得有转移方程.我们令f[i]表示让i子树中的 ...

  5. 【洛谷】P4643 【模板】动态dp

    题解 在冬令营上听到冬眠的东西,现在都是板子了猫锟真的是好毒瘤啊(雾) (立个flag,我去thusc之前要把WC2018T1乱搞过去= =) 好的,我们可以参考猫锟的动态动态dp的课件,然后你发现你 ...

  6. 「LGP4719【模板】动态dp」

    题目 尽管知道这个东西应该不会考了,但是还是学一学吧 哎要是去年noip之前学该多好 动态\(dp\)就是允许修改的一个\(dp\),比如这道题,我们都知道这是一个树上最大点权独立集 众所周知方程长这 ...

  7. 洛谷 P4719 【模板】动态dp【动态dp】

    是动态dp的板子 大致思想就是用g[u]来表示不包含重链转移的dp值,然后用线段树维护重链,这样线段树的根就相当于这条重链的top的真实dp值 每次修改的时候,修改x点会影响到x到根的真实dp值,但是 ...

  8. bzoj5210 最大连通子块和 动态 DP + 堆

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5210 题解 令 \(dp[x][0]\) 表示以 \(x\) 为根的子树中的包含 \(x\) ...

  9. 模版 动态 dp

    模版 动态 dp 终于来写这个东西了.. LG 模版:给定 n 个点的数,点有点权, $ m $ 次修改点权,求修改完后这个树的最大独立集大小. 我们先来考虑朴素的最大独立集的 dp \[dp[u][ ...

随机推荐

  1. Java转python第一天

    1.python xx.py 2.字符串可以与数字相乘 str = "abc" msg = str*3 print(msg) # 结果:abcabcabc 3.换行用三个单引号 ' ...

  2. 03-Python执行方式和Pycharm设置

    https://www.python.org/ 单词列表 * error 错误 * name 名字 * defined 已经定义 * syntax 语法 * invalid 无效 * Indentat ...

  3. VS编程,WPF中两个滚动条 ScrollViewer 同步滚动的一种方法

    原文:VS编程,WPF中两个滚动条 ScrollViewer 同步滚动的一种方法 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/ar ...

  4. Source insight 中 标题栏路径显示完整路径的方法

    在source insight 的标题栏中显示完整路径名的方法.Options -> Preferences -> Display -> Trim long path names w ...

  5. windows系统中Dotnet core runtime 安装后,无法启动次程序,因为计算机中丢失api-ms-win-crt-runtime-l1-1-0.dll的解决方法

    因为dotnet core runtime依赖vc++2015,如果系统未安装vc++2015则会报上面的错误 解决方案:先下载安装vc++2015再安装dotnet core runtime, vc ...

  6. idea 开启 tomcat 访问日志记录

    all 为 设置为 查看所有类型的请求 (包括ajax)

  7. Java 多线程(三)之线程状态及其验证

    目录 线程状态 Thread.State 状态类型 定义 说明 状态转换 状态验证 「NEW」-> 「RUNNABLE」 -> 「TERMINATED」 「RUNNABLE」 -> ...

  8. Android与单片机通信常用数据转换方法(汇总)

    下面直接贴代码 1.  将GB2312转化为中文,如BAFAC2DCB2B7→胡萝卜,两个字节合成一个文字 public static String stringToGbk(String string ...

  9. nodejs安装及npm模块插件安装路径配置

    在学习完js后,我们就要进入nodejs的学习,因此就必须配置nodejs和npm的属性了. 我相信,个别人在安装时会遇到这样那样的问题,看着同学都已装好,难免会焦虑起来.于是就开始上网查找解决方案, ...

  10. RabbitMq基础教程之基本概念

    RabbitMq基础教程之基本概念 RabbitMQ是一个消息队列,和Kafka以及阿里的ActiveMQ从属性来讲,干的都是一回事.消息队列的主要目的实现消息的生产者和消费者之间的解耦,支持多应用之 ...