题目: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. git 强制覆盖,分支合并

    强制合并 git fetch --all && git reset --hard origin/master && git pull 合并代码 git commit - ...

  2. linux遍历目录源代码

    <pre code_snippet_id="1622396" snippet_file_name="blog_20160324_1_744516" nam ...

  3. tempdb 相关总结

    /* -- 0. 高速压缩tempdb为初始值 USE tempdb DBCC SHRINKFILE(2,TRUNCATEONLY); */ -- 1. tempdb以下未回收的暂时表 ,某些版本号可 ...

  4. python(36)- 测试题

    1.8<<2等于? 32 “<<”位运算 264 132 64 32 16 8 4 2 1 原始位置 0 0 0 0 0 1 0 0 0 想左位移2位 0 0 0 1 0 0 ...

  5. WPF简单计算器

  6. openshifit 安装 redis

    http://blog.csdn.net/lsx991947534/article/details/48860537 http://blog.csdn.net/aguangg_6655_la/arti ...

  7. oracle sql 当初始化数据时避免重复主键

    一:当有主键序列自动增长时候(序列为:seq_cct_id) insert into cs_cost_type (CCT_ID, CCT_NAME, CCT_RATE, CCT_RATE_TYPE, ...

  8. RestTemplate请求

    JSONObject json = new JSONObject(sendParam);HttpHeaders headers = new HttpHeaders();MediaType type = ...

  9. Topcoder SRM 638 DIV 2 (大力出奇迹)

    水题,就是一个暴力.大力出奇迹. Problem Statement   There is a narrow passage. Inside the passage there are some wo ...

  10. Android SDK 更新不下来解决方法

    国内的小伙伴是不是更新SDK总是更新不动呢,小弟找到一个好的解决方式,把SDK的全部都下载全了也就用了一个小时,匀速2M/s. 解决方法是改动win7的host文件. 路径:C:\Windows\Sy ...