题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4712

设 f[x] = min(∑f[u] , a[x]),ls = ∑f[lson]

矩阵是这样的:

ls, a[x]

0, 0

所以假如后面乘一个

f[u], 0

0, 0

就得到了 f[x];

注意,因为定义结构体时把数组都赋成 inf 了,所以后面要用 0 时必须专门赋值成 0;

查询时不是从重链顶开始的,所以不用 get,直接 query(x,ed[top[x]]);

最后 f[x] 和 a[x] 再取一下 min 即可(相当于乘全是0的矩阵)。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mid ((l+r)>>1)
#define ls (x<<1)
#define rs (x<<1|1)
using namespace std;
typedef long long ll;
int const xn=2e5+;
int n,hd[xn],ct,to[xn<<],nxt[xn<<],fa[xn],dfn[xn],siz[xn],son[xn];
int id[xn],tim,top[xn],ed[xn];
ll a[xn],f[xn],inf=1e10;
ll mnn(ll a,ll b){return a<b?a:b;}
struct N{
ll a[][];
N(){a[][]=a[][]=a[][]=a[][]=inf;}
N operator * (const N &y) const
{
N ret;
for(int i=;i<;i++)
for(int k=;k<;k++)
for(int j=;j<;j++)
ret.a[i][j]=mnn(ret.a[i][j],a[i][k]+y.a[k][j]);
return ret;
}
}t[xn<<],s[xn];
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
return f?ret:-ret;
}
void add(int x,int y){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct;}
void dfs(int x,int ff)
{
fa[x]=ff; siz[x]=;
for(int i=hd[x],u;i;i=nxt[i])
{
if((u=to[i])==ff)continue;
dfs(u,x); siz[x]+=siz[u];
if(siz[u]>siz[son[x]])son[x]=u;
}
}
void dfs2(int x)
{
dfn[x]=++tim; id[tim]=x; f[x]=a[x]; ll tmp=;
s[dfn[x]].a[][]=inf; s[dfn[x]].a[][]=a[x];//
s[dfn[x]].a[][]=s[dfn[x]].a[][]=;//!!!
if(son[x])top[son[x]]=top[x],dfs2(son[x]);
else {ed[top[x]]=dfn[x]; return;}//!son: a[0][0]=inf
for(int i=hd[x],u;i;i=nxt[i])
if((u=to[i])!=fa[x]&&u!=son[x])
{
top[u]=u; dfs2(u);
tmp+=f[u];
}
s[dfn[x]].a[][]=tmp;
f[x]=mnn(a[x],tmp+f[son[x]]);
}
void build(int x,int l,int r)
{
if(l==r){t[x]=s[l]; return;}
build(ls,l,mid); build(rs,mid+,r);
t[x]=t[ls]*t[rs];
}
void upt(int x,int l,int r,int pos)
{
if(l==r){t[x]=s[l]; return;}
if(pos<=mid)upt(ls,l,mid,pos);
else upt(rs,mid+,r,pos);
t[x]=t[ls]*t[rs];
}
N query(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R)return t[x];
if(mid>=R)return query(ls,l,mid,L,R);
if(mid<L)return query(rs,mid+,r,L,R);
return query(ls,l,mid,L,R)*query(rs,mid+,r,L,R);
}
N get(int x){return query(,,n,dfn[x],ed[x]);}
void chg(int x,int ss)
{
s[dfn[x]].a[][]+=ss;//dfn[x]
N pr,nw;
while(x)
{
pr=get(top[x]); upt(,,n,dfn[x]); nw=get(top[x]);
x=fa[top[x]];
s[dfn[x]].a[][]+=mnn(nw.a[][],nw.a[][])-mnn(pr.a[][],pr.a[][]);//
}
}
char ch[];
int main()
{
n=rd();
for(int i=;i<=n;i++)a[i]=rd();
for(int i=,x,y;i<n;i++)x=rd(),y=rd(),add(x,y),add(y,x);
dfs(,); top[]=; dfs2(); build(,,n);
int m=rd();
for(int i=,x,v;i<=m;i++)
{
scanf("%s",ch); x=rd();
if(ch[]=='C')v=rd(),chg(x,v);
else
{
N tmp=query(,,n,dfn[x],ed[top[x]]);//
printf("%lld\n",mnn(tmp.a[][],tmp.a[][]));
}
}
return ;
}

bzoj 4712 洪水 —— 动态DP的更多相关文章

  1. bzoj 4712 洪水——动态DP

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

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

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

  3. BZOJ 4712 洪水 (线段树+树剖动态维护DP)

    题目大意:略 题目传送门 数据结构好题,但据说直接上动态DP会容易处理不少,然而蒟蒻不会.一氧化碳大爷说还有一个$log$的做法,然而我只会$log^{2}$的.. 考虑静态时如何处理,设$f[x]$ ...

  4. bzoj 4712: 洪水

    [权限题][https://www.lydsy.com/JudgeOnline/status.php?problem_id=4712&jresult=4] 这道动态\(dp\)终于不是独立集/ ...

  5. 【bzoj4712】洪水 动态dp

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

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

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

  7. BZOJ 4712: 洪水 挖坑待补

    Code: #include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) # ...

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

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

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

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

随机推荐

  1. 醒醒吧少年,只用Cucumber不能帮助你BDD

    转载:http://insights.thoughtworkers.org/bdd/ 引言 在Ruby社区中,测试和BDD一直是被热议的话题,不管是单元测试.集成测试还是功能测试,你总能找到能帮助你的 ...

  2. js 节点操作

    添加和删除节点(HTML 元素). 创建新的 HTML 元素 如需向 HTML DOM 添加新元素,您必须首先创建该元素(元素节点),然后向一个已存在的元素追加该元素. 实例 <div id=& ...

  3. php实现双色球算法

    function DoubleBall(){ $sysBlueball = mt_rand(1,16); $sysRedball = array(1,2,3,4,5,6,7,8,9,10,11,12, ...

  4. android等待旋转圆圈动画

    先创建一个动画的xml文件例如以下 <? xml version="1.0" encoding="utf-8"?> <animation-li ...

  5. 后台运行命令:&amp;和nohup command &amp; 以及关闭、查看后台任务

    当我们在终端或控制台工作时.可能不希望由于执行一个作业而占住了屏幕,由于可能还有更重要的事情要做,比方阅读电子邮件. 对于密集訪问磁盘的进程,我们更希望它可以在每天的非负荷高峰时间段执行(比如凌晨). ...

  6. mysql查询sql中检索条件为大批量数据时处理

    当userIdArr数组值为大批量时,应如此优化代码实现

  7. 对H.264帧类型判断方法

    背景描述 我们经常在网络直播推流或者客户端拉流的时候,需要对获取到的H.264视频帧进行判断后处理,我们经常获取到各种不同的视频数据0x67 0x68 0x65 0x61,0x27 0x28 0x25 ...

  8. EasyDarwin开源社区流媒体视频课程:流媒体传输控制协议(RTSP RTP SDP)详解之sdp

    视频课程及相关文档代码地址:https://github.com/EasyDarwin/Course#course-3 SDP协议 一.SDP协议介绍 SDP 完全是一种会话描述格式(对应的RFC23 ...

  9. Eclipse中同时打开多个Console

    实现方法: 1.点击Open Console案例下拉三角,选择New Console View. 2.点击Pin Console按钮將两个控制台同时固定住. 3.点击Display Selected ...

  10. IOS 文件夹结构

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/MyGameZone/article/details/24494765 IOS文件夹结构 说明 这些仅 ...