不难发现此题是一道动态$dp$题

考虑此题没有修改怎么做,令$f[i]$表示让以$i$为根的子树被覆盖的最小花费,不难推出$f[i]=min(\sum_{j∈son[i]} f[j],val[i])$。

依然采用树链剖分+线段树维护每一条链。线段树上每个节点维护$val1$和$val2$两个值。

其中$val1$表示$\sum_{(fa[i]∈U)\&(i∉V)}f[i]$。U为该区间上点的点集,V为该区间所在链的点集。

$val2$表示以区间右端点为根的子树被覆盖的最小代价。

这东西随便维护一下就可以了(详见代码)

修改的话,我们先更新一下当前节点所在的链值,并将这个更新传递到上一条链去即可。

 #include<bits/stdc++.h>
#define M 200005
#define mid ((a[x].l+a[x].r)>>1)
#define L long long
using namespace std; struct edge{int u,next;}e[M*]={}; int head[M]={},use=;
void add(int x,int y){use++;e[use].u=y;e[use].next=head[x];head[x]=use;} int dfn[M]={},rec[M]={},siz[M]={},fa[M]={},son[M]={},top[M]={},dn[M]={},t=;
void dfs(int x){
siz[x]=;
for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa[x]){
fa[e[i].u]=x; dfs(e[i].u);
siz[x]+=siz[e[i].u]; if(siz[son[x]]<siz[e[i].u]) son[x]=e[i].u;
}
}
void dfs(int x,int Top){
dfn[x]=++t; rec[t]=x; top[x]=Top;
if(son[x]) dfs(son[x],Top),dn[x]=dn[son[x]]; else dn[x]=x;
for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa[x]&&e[i].u!=son[x]) dfs(e[i].u,e[i].u);
}
L f[M]={},val[M]={};
void dp(int x){
if(dn[x]==x) f[x]=val[x];
for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa[x]) dp(e[i].u),f[x]+=f[e[i].u];
f[x]=min(f[x],val[x]);
} struct mat{
L f,g; mat(){f=g=;}
mat(L F,L G){f=F; g=G;}
friend mat operator +(mat a,mat b){
mat c;
c.f=min(a.f,a.g+b.f);
c.g=min(a.g+b.g,c.f);
return c;
}
}wei[M];
struct seg{int l,r; mat s;}a[M<<];
void pushup(int x){a[x].s=a[x<<].s+a[x<<|].s;} void build(int x,int l,int r){
a[x].l=l; a[x].r=r;
if(l==r){
L G=; int u=rec[l];
for(int i=head[u];i;i=e[i].next)
if(e[i].u!=fa[u]&&e[i].u!=son[u]){
G+=f[e[i].u];
}
a[x].s=wei[l]=mat(val[u],G);
return;
}
build(x<<,l,mid); build(x<<|,mid+,r);
pushup(x);
}
void updata(int x,int k){
if(a[x].l==a[x].r) return void(a[x].s=wei[k]);
if(k<=mid) updata(x<<,k); else updata(x<<|,k);
pushup(x);
}
mat query(int x,int l,int r){
if(l<=a[x].l&&a[x].r<=r) return a[x].s;
if(r<=mid) return query(x<<,l,r);
if(mid<l) return query(x<<|,l,r);
return query(x<<,l,r)+query(x<<|,l,r);
}
mat query(int x){return query(,dfn[top[x]],dfn[dn[x]]);} void Updata(int x,L Val){
wei[dfn[x]].f+=Val; val[x]+=Val;
while(x){
mat last=query(x);
updata(,dfn[x]);
mat now=query(x); x=fa[top[x]]; if(!x) return; wei[dfn[x]].g+=now.f-last.f;
}
} int n;
main(){
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%lld",val+i);
for(int i=,x,y;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
dfs();
dfs(,);
dp();
build(,,n);
int m; scanf("%d",&m);
while(m--){
char op[]; L x,y;
scanf("%s%lld",op,&x);
if(op[]=='Q'){
mat res=query(,dfn[x],dfn[dn[x]]);
printf("%lld\n",res.f);
}else{
scanf("%lld",&y);
Updata(x,y);
}
}
}

【bzoj4712】洪水 动态dp的更多相关文章

  1. BZOJ4712洪水——动态DP+树链剖分+线段树

    题目描述 小A走到一个山脚下,准备给自己造一个小屋.这时候,小A的朋友(op,又叫管理员)打开了创造模式,然后飞到 山顶放了格水.于是小A面前出现了一个瀑布.作为平民的小A只好老实巴交地爬山堵水.那么 ...

  2. bzoj 4712 洪水——动态DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4712 因为作为动态DP练习而找到,所以就用动态DP做了,也没管那种二分的方法. 感觉理解似乎 ...

  3. bzoj 4712 洪水 —— 动态DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4712 设 f[x] = min(∑f[u] , a[x]),ls = ∑f[lson] 矩阵 ...

  4. BZOJ 4712 洪水 动态dp(LCT+矩阵乘法)

    把之前写的版本改了一下,这个版本的更好理解一些. 特地在一个链的最底端特判了一下. code: #include <bits/stdc++.h> #define N 200005 #def ...

  5. 【BZOJ4712】洪水(动态dp)

    [BZOJ4712]洪水(动态dp) 题面 BZOJ 然而是权限题QwQ,所以粘过来算了. Description 小A走到一个山脚下,准备给自己造一个小屋.这时候,小A的朋友(op,又叫管理员)打开 ...

  6. [bzoj4712]洪水_动态dp

    洪水 bzoj-4712 题目大意:给定一棵$n$个节点的有根树.每次询问以一棵节点为根的子树内,选取一些节点使得这个被询问的节点包含的叶子节点都有一个父亲被选中,求最小权值.支持单点修改. 注释:$ ...

  7. 【bzoj4712】洪水 树链剖分+线段树维护树形动态dp

    题目描述 给出一棵树,点有点权.多次增加某个点的点权,并在某一棵子树中询问:选出若干个节点,使得每个叶子节点到根节点的路径上至少有一个节点被选择,求选出的点的点权和的最小值. 输入 输入文件第一行包含 ...

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

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

  9. 动态 DP 学习笔记

    不得不承认,去年提高组 D2T3 对动态 DP 起到了良好的普及效果. 动态 DP 主要用于解决一类问题.这类问题一般原本都是较为简单的树上 DP 问题,但是被套上了丧心病狂的修改点权的操作.举个例子 ...

随机推荐

  1. Silverlight或WPF动态绑定图片路径问题,不用Converter完美解决

    关于Silverlight或WPF动态绑定图片路径问题,不用Converter完美解决, 可想,一个固定的字符串MS都能找到,按常理动态绑定也应该没问题的,只需在前面标记它是一个Path类型的值它就能 ...

  2. 原生js:click和onclick本质的区别

    原生javascript的click在w3c里边的阐述是DOM button对象,也是html DOM click() 方法,可模拟在按钮上的一次鼠标单击. button 对象代表 HTML 文档中的 ...

  3. js如何实现网站title的滚动效果

    var text=document.title;//获得页面的标题            var timerID;//定时器            function newtext() {       ...

  4. 2018.08.30 NOIP模拟 wall(模拟)

    [问题描述] 万里长城是中国强大的标志,长城在古代的用途主要用于快速传递军事消息和抵御 外敌,在长城上的烽火台即可以作为藏兵的堡垒有可以来点燃狼烟传递消息. 现在有一段 万里长城,一共有 N 个烽火台 ...

  5. VMware + LInux + Xshell 连接环境设置(心得体会)

    准备好VMware软件,和Linux 和xshell三款软件,下载和安装好,这里VMware是十二,Linux是CentOs 6 ,xshell是5 其实没有什么区别只要版本兼容就行,我们就可以实现远 ...

  6. spark 与 hbase-server 集成版本问题

    今天在使用spark存储hbase的时候遇到异常Exception in thread "main" java.lang.NoSuchMethodError: io.netty.b ...

  7. 在linux系统中安装VSCode(Visual Studio Code)和图标的创建方式

    本文转载自:https://www.cnblogs.com/lzpong/p/6145511.html,自己添加了一些关于依赖包安装的. 1.从官网下载压缩包(话说下载下来解压就直接可以运行了咧,都不 ...

  8. ansible-playbook 主机变量2

    ansible-playbook 配置 hosts 后可以指定变量,通过-k 可以交互输入密码,也可以将密码写在 hosts 文件中. 入口 yaml 文件中通过 {{ ** }} 获取变量,命令行通 ...

  9. OpenGL中位图的操作(glReadPixels,glDrawPixels等)

    OpenGL中位图的操作 OpenGL中位图的操作(glReadPixels,glDrawPixels和glCopyPixels应用举例). 1. BMP文件格式简单介绍 BMP文件是一种像素文件,它 ...

  10. hdu 4946 凸包注意重点

    http://acm.hdu.edu.cn/showproblem.php?pid=4946 给你n个点的坐标和速度,如果一个点能够到达无穷远处,且花费的时间是最少的,则此点输出1,否则输出0. 每个 ...