不难发现此题是一道动态$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. JavaScript中的 prototype 和 constructor

    prototype属性  任何js函数都可以用作构造函数, 而构造函数需要用到prototype属性, 因此, 每个js函数F(除了ES5的Function.bind()方法返回的函数外) 都自动拥有 ...

  2. Devexpress VCL Build v2013 vol 14.1.5 发布

    What's New in 14.1.5 (VCL Product Line)   New Major Features in 14.1 What's New in VCL Products 14.1 ...

  3. 2018.10.14 loj#6003. 「网络流 24 题」魔术球(最大流)

    传送门 网络流好题. 这道题可以动态建图. 不难想到把每个球iii都拆点成i1i_1i1​和i2i_2i2​,每次连边(s,i1),(i2,t)(s,i_1),(i_2,t)(s,i1​),(i2​, ...

  4. 第七章 介词(La préposition )

    法语中的介词是将两个同类或非同类的词连接在一起,把一个句中成分同另一个句子成分联系起来,并表明两者之间关系的词类.介词是一种无词性变化的词类. ★介词的形式 ()简单形式的介词,如: ()复合形式的介 ...

  5. POJ 2376 Cleaning Shifts (贪心,区间覆盖)

    题意:给定1-m的区间,然后给定n个小区间,用最少的小区间去覆盖1-m的区间,覆盖不了,输出-1. 析:一看就知道是贪心算法的区间覆盖,主要贪心策略是把左端点排序,如果左端点大于1无解,然后, 忽略小 ...

  6. linux常见命令整理

    Linux管理文件和目录的命令 命令 功能 命令 功能 pwd 显示当前目录 ls 查看目录下的内容 cd 改变所在目录 cat 显示文件的内容 grep 在文件中查找某字符 cp 复制文件 touc ...

  7. Scrapy爬取美女图片第三集 代理ip(上) (原创)

    首先说一声,让大家久等了.本来打算那天进行更新的,可是一细想,也只有我这样的单身狗还在做科研,大家可能没心思看更新的文章,所以就拖到了今天.不过忙了521,522这一天半,我把数据库也添加进来了,修复 ...

  8. oracle 游标实现多重循环

    declare -- Local variables here i integer; cursor c_province is select ds.swjg_dm from dm_swjg ds wh ...

  9. jenkins 后台程序运行

    # 背景 jenkins持续集成,需要任务后台执行(nohup执行)结果发现jenkins的job执行完后,看不到运行的进程 # 步骤 原因就是这么一个情况:Jenkins任务结束时候自动关掉了所有的 ...

  10. 设计模式之外观模式(Facade Pattern)

    一.什么是外观模式? 简单的说,外观模式是用来简化接口的. 通常,我们觉得一个子系统不好用,可能是因为它提供的外部接口太接近低层组件,让我们用起来感到很麻烦. 因为我们不需要知道内部细节,我们只想要一 ...