动态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. 设计模式 笔记 命令模式 Command

    //---------------------------15/04/25---------------------------- //Conmmand  命令模式----对象行为型模式 /* 1:意 ...

  2. jquery原理的简单分析,让你扒开jquery的小外套。

    引言 最近LZ还在消化系统原理的第三章,因此这部分内容LZ打算再沉淀一下再写.本次LZ和各位来讨论一点前端的内容,其实有关jquery,在很久之前,LZ就写过一篇简单的源码分析.只不过当时刚开始写博客 ...

  3. 杂谈---小故事小道理,面试中的小技巧(NO.2)

    本篇是接着上一篇面试随笔的,上一次有猿友反应写的有些“扯淡”,LZ思来想去最大的原因可能是由于上一章写的全是一些大忌,既然是大忌,那么在现实当中发生的概率还是相对较小的,大部分人还是很少在面试中犯如此 ...

  4. Jq_网站顶部定时折叠广告

    <!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head><titl ...

  5. numpy 初识(一)

    基本操作: 读取文件(与pandas读取csv相似): import numpy numpy.genfromtxt("word.txt", delimiter=',', dtype ...

  6. 企业落地Kubernetes的问题与对策

    在当今云计算领域,“容器技术”已经从三四年前的炒作期正式进入了产业落地期,而Kubernetes作为容器平台的标准已经得到了广泛应用. Kubernetes从2014年6月由Google宣布开源,到2 ...

  7. VC++ 屏蔽掉警告

    使用VC6.0在开发程序的时候经常会遇到很多警告,很麻烦,也很耽误时间,可以使用如下方法屏蔽掉警告 在StdAfx.h 中 #define VC_EXTRALEAN 下面增加:#pragma warn ...

  8. Android webview背景设置为透明无效 拖动时背景闪烁黑色

    Adndroid 2.X的设置 webview是一个使用方便.功能强大的控件,但由于webview的背景颜色默认是白色,在一些场合下会显得很突兀(比如背景是黑色). 此时就想到了要把webview的背 ...

  9. MYSQL数据库封装类

    <?phpclass DBDA{    public $host="localhost";    public $uid="root";    publi ...

  10. C++ 多态Polymorphism 介绍+动态绑定、静态绑定

    什么是多态? 多态(polymorphism)一词最初来源于希腊语polumorphos,含义是一种物质的多种形态. 在专业术语中,多态是一种运行时绑定机制(run-time binding) ,通过 ...