动态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. IDEA创建Scala项目

    一.安装插件 见Scala入门篇 二.新建项目 选择new project,其中SBT相当于精简版的maven,其他的待补充.这里选择IDEA 填写信息,选择Scala SDK 在src目录下新建Sc ...

  2. 20155234 Exp2 后门原理与实践

    Windows获得Linux Shell 1.查看ip 2.监听端口 3.实验成功如下图 Linux获得Win Shell 1.查看虚拟机ip 2.监听端口 3.实验成功如下图 使用NC传输数据 1. ...

  3. JavaEE笔记(十二)

    代理的三种配置 beans配置文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=& ...

  4. PX Deq: Execution Msg 等待事件

    可参考 MOS文档: WAITEVENT: "PX Deq Credit: send blkd" (Doc ID 271767.1) P1 = sleeptime/senderid ...

  5. 汇编 XOR运算

     XOR运算  按位异或^ 一.按位异或^ 运算符^ 1^1=0;0^0=0; //相同则为0 0^1=1;1^0=1; //不相同为1 1101^0110=1011; // asm_XOR.c ...

  6. 3. Python3 基本数据类型

    Python3 基本数据类型 Python 中的变量不需要声明.每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建. 在 Python 中,变量就是变量,它没有类型,我们所说的"类型& ...

  7. JavaScript中执行环境和栈

    在这篇文章中,我会深入理解JavaScript最根本的组成之一 : "执行环境(执行上下文)".文章结束后,你应该对解释器试图做什么,为什么一些函数/变量在未声明时就可以调用并且他 ...

  8. 主流蓝牙芯片盘点,Nordic/TI/博通哪家强?

    无线通信技术自19世纪中期诞生以来,从使用狼烟.火炬.闪光镜.信号弹等在视距内传输信息,到1838年塞缪尔・莫尔斯发明电报网,再到电报网被电话取代,再到几十年后的1895年马可尼首次从英国怀特岛到30 ...

  9. c# 简易绘制C语言头文件包含关系图 v2.0

    老规矩,先上图 节点样式说明: 1.粉色圆角,说明该节点下有循环引用 2.黄色菱形,说明该节点代表的文件在项目目录下未找到. 3.红色圆角,说明循环引用(从开始到最终,这种感情没变过,没有谁..... ...

  10. 关于 error C2039: “create”: 不是“cocos2d::GLView”的成员的解决方法

    问题: 跑一个demo,因为是涉及3.x版本的引擎,不是很熟悉,在VS2013上运行,报错 error C2039: “create”: 不是“cocos2d::GLView”的成员 解决: 通过查阅 ...