题解:

注意题目说了每个点的权值只能增加

每个点的dp方程比较简单 min(v[i],sum[i])

那么我们考虑如果v[i]增加那么上面使用sum[i]的会带来影响

暴力的做就是一个个往上查然后修改

比较显然的是这个东西可以二分

我们维护v[i]-sum[i]的值,查到那个不符合的就可以了

这样我们就变成了花log^2n的时间对v[i]>sum[i]的变成v[i]<sum[i]

而每次操作最多增加一个v[i]>sum[i]

所以复杂度是对的

树链剖分维护,复杂度nlog^2n

还是比较考验代码能力的

树剖那里一定要理清楚思路

代码:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. #define rint register ll
  5. #define rll register ll
  6. #define IL inline
  7. #define rep(i,h,t) for (rint i=h;i<=t;i++)
  8. #define dep(i,t,h) for (rint i=t;i>=h;i--)
  9. const ll N=2e5+1e4;
  10. const ll N2=N*;
  11. const ll INF=1e9;
  12. ll n,m,v[N],head[N],id[N],rel[N],yz[N],fa[N],f[N],son[N],g[N],num[N],top[N],l;
  13. ll data[N2],cnt,lazy[N2];
  14. struct re{
  15. ll a,b,c;
  16. }e[N*];
  17. void arr(ll x,ll y)
  18. {
  19. e[++l].a=head[x];
  20. e[l].b=y;
  21. head[x]=l;
  22. }
  23. void dfs(ll x,ll y)
  24. {
  25. f[x]=v[x]; num[x]=; fa[x]=y;
  26. ll sum=;
  27. for (rint u=head[x];u;u=e[u].a)
  28. {
  29. rint v=e[u].b;
  30. if (v!=y)
  31. {
  32. yz[x]=;
  33. dfs(v,x);
  34. sum+=f[v];
  35. num[x]+=num[v];
  36. if (num[v]>num[son[x]]) son[x]=v;
  37. }
  38. }
  39. if (sum) f[x]=min(f[x],sum);
  40. if (sum) g[x]=sum; else g[x]=f[x];
  41. }
  42. void dfs2(ll x,ll y,ll z)
  43. {
  44. id[x]=++cnt; rel[cnt]=x;
  45. top[x]=y;
  46. if (!son[x]) return;
  47. dfs2(son[x],y,x);
  48. for (rint u=head[x];u;u=e[u].a)
  49. {
  50. rint v=e[u].b;
  51. if (v!=z&&v!=son[x]) dfs2(v,v,x);
  52. }
  53. }
  54. #define updata(x) data[x]=min(data[x*2],data[x*2+1])
  55. #define mid ((h+t)/2)
  56. IL void down(ll x)
  57. {
  58. if (!lazy[x]) return;
  59. lazy[x*]+=lazy[x]; lazy[x*+]+=lazy[x];
  60. data[x*]-=lazy[x]; data[x*+]-=lazy[x];
  61. lazy[x]=;
  62. }
  63. void build(ll x,ll h,ll t)
  64. {
  65. if (h==t)
  66. {
  67. data[x]=v[rel[h]]-g[rel[h]];
  68. return;
  69. }
  70. build(x*,h,mid); build(x*+,mid+,t);
  71. updata(x);
  72. }
  73. ll query(ll x,ll h,ll t,ll pos)
  74. {
  75. if (h==t)
  76. {
  77. if (data[x]>) return(v[rel[h]]-data[x]);
  78. else return(v[rel[h]]);
  79. }
  80. down(x);
  81. if (pos<=mid) return(query(x*,h,mid,pos));
  82. else return(query(x*+,mid+,t,pos));
  83. updata(x);
  84. }
  85. void change2(ll x,ll h,ll t,ll h1,ll t1,ll k)
  86. {
  87. if (h1<=h&&t<=t1)
  88. {
  89. lazy[x]+=k; data[x]-=k; return;
  90. }
  91. down(x);
  92. if (h1<=mid) change2(x*,h,mid,h1,t1,k);
  93. if (mid<t1) change2(x*+,mid+,t,h1,t1,k);
  94. updata(x);
  95. }
  96. ll query2(ll x,ll h,ll t,ll h1,ll t1)
  97. {
  98. if (h1<=h&&t<=t1)
  99. {
  100. return(data[x]);
  101. }
  102. down(x);
  103. ll ans=INF;
  104. if (h1<=mid) ans=min(ans,query2(x*,h,mid,h1,t1));
  105. if (mid<t1) ans=min(ans,query2(x*+,mid+,t,h1,t1));
  106. return(ans);
  107. }
  108. vector<re> ve;
  109. void find2(ll x,ll h,ll t,ll h1,ll t1)
  110. {
  111. if (h1<=h&&t<=t1)
  112. {
  113. ve.push_back((re){x,h,t}); return;
  114. }
  115. down(x);
  116. if (h1<=mid) find2(x*,h,mid,h1,t1);
  117. if (mid<t1) find2(x*+,mid+,t,h1,t1);
  118. }
  119. ll find3(ll x,ll h,ll t,ll k)
  120. {
  121. if (h==t) return(h);
  122. down(x);
  123. if (data[x*+]<k) return(find3(x*+,mid+,t,k));
  124. else return(find3(x*,h,mid,k));
  125. }
  126. void change(rll x,rll y)
  127. {
  128. if (!y) return;
  129. rll now=x;
  130. while (top[now])
  131. {
  132. if (query2(,,n,id[top[now]],id[now])>=y)
  133. {
  134. change2(,,n,id[top[now]],id[now],y); //v[x]-g[x] 减小y
  135. } else
  136. {
  137. ve.clear();
  138. find2(,,n,id[top[now]],id[now]);
  139. rll l=int(ve.size())-;
  140. rll k;
  141. dep(i,l,)
  142. if (data[ve[i].a]<y)
  143. {
  144. k=find3(ve[i].a,ve[i].b,ve[i].c,y); // k.a 位置 k.b v[x]-g[x]
  145. break;
  146. }
  147. rll x1=query(,,n,k);
  148. change2(,,n,k,id[now],y);
  149. rll x2=query(,,n,k);
  150. change(fa[rel[k]],x2-x1);
  151. break;
  152. }
  153. now=fa[top[now]];
  154. }
  155. }
  156. int main()
  157. {
  158. freopen("1.in","r",stdin);
  159. freopen("1.out","w",stdout);
  160. ios::sync_with_stdio(false);
  161. cin>>n;
  162. rep(i,,n) cin>>v[i];
  163. rep(i,,n-)
  164. {
  165. ll x,y; cin>>x>>y;
  166. arr(x,y); arr(y,x);
  167. }
  168. dfs(,);
  169. dfs2(,,);
  170. build(,,n);
  171. cin>>m;
  172. char cc;
  173. rep(i,,m)
  174. {
  175. ll x,y;
  176. cin>>cc;
  177. if (cc=='Q')
  178. {
  179. cin>>x;
  180. cout<<query(,,n,id[x])<<endl;
  181. } else
  182. {
  183. cin>>x>>y;
  184. ll x1=query(,,n,id[x]);
  185. v[x]+=y;
  186. if (yz[x])
  187. {
  188. change2(,,n,id[x],id[x],-y);
  189. ll x3=query(,,n,id[x]);
  190. if (x3>x1) change(fa[x],x3-x1);
  191. }
  192. else change(fa[x],y);
  193. }
  194. }
  195. return ;
  196. }

【BZOJ4712】洪水的更多相关文章

  1. [bzoj4712]洪水_动态dp

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

  2. BZOJ4712 : 洪水

    首先不难列出DP方程: $dp[x]=\min(w[x],h[x])$ $h[x]=\sum dp[son]$ 当$w[x]$增加时,显然$dp[x]$不会减少,那么我们求出$dp[x]$的增量$de ...

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

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

  4. 2018.10.12 bzoj4712: 洪水(树链剖分)

    传送门 树链剖分好题. 考虑分开维护重儿子和轻儿子的信息. 令f[i]f[i]f[i]表示iii为根子树的最优值,h[i]h[i]h[i]表示iii重儿子的最优值,g[i]g[i]g[i]表示iii所 ...

  5. [bzoj4712]洪水 线段树+树链剖分维护动态dp+二分

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

  6. [BZOJ4712]洪水-[树链剖分+线段树]

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

  7. [bzoj4712] 洪水 [树链剖分+线段树+dp]

    题面 传送门 思路 DP方程 首先,这题如果没有修改操作就是sb题,dp方程如下 $dp[u]=max(v[u],max(dp[v]))$,其中$v$是$u$的儿子 我们令$g[u]=max(dp[v ...

  8. BZOJ4712: 洪水(树链剖分维护Dp)

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

  9. bzoj4712 洪水(动态dp)

    看起来很模板的一个题啊 qwq 但是我还是wei 题目要求的是一个把根节点和所有叶子断开连接的最小花费. 还是想一个比较\(naive\)的做法 我们令\(dp1[i]\)表示,在\(i\)的子树内, ...

  10. 动态 DP 学习笔记

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

随机推荐

  1. strncpy的用法

    strncpy是C语言的库函数之一,来自C语言标准库,定义于string.h,函数原型是: char *strncpy(char* dest,char* src,size_t n); 把src所指向的 ...

  2. page.isvalid

    背景 看到这个标题,想了半天,为啥用的.应该是当初前台要动态增加行这个事情,当初用.net真是用傻了,竟然对html.aspx原理不大清楚,对于html也想着后台生成.真是弱智啊.谈到这里,想到c#这 ...

  3. JS导出excel设置下载的标题/与angular结合冲突

    2017.8更新 此功能与angular结合使用时,最后一行 document.getElementById("dlink").click(); 与angular的ng-click ...

  4. Record && Limit

    案例一:Record 预期效果:在 IVR 与用户交互的时候,比如让用户读一段语音,当用户读完之后,按键结束录音. <action application="set" dat ...

  5. Python-Django-Ajax进阶

    ajax上传文件: <h2>基于ajax上传文件</h2><p>名字 <input type="text" id="filena ...

  6. vue打包项目后使用-webkit-line-clamp: 2;这个属性不生效?

    在项目中要实现多行省略,-webkit-line-clamp: 2;打包后不生效,使用下面的方法: word-break: break-all; text-overflow: ellipsis; di ...

  7. GitHub访问慢

    问题描述 一直都觉得访问 GitHub 时速度非常慢,刷新一下都要等好久!于是尝试一下能否解决掉... github.com assets-cdn.github.com avatar2.githubu ...

  8. Java感情

    不知道怎么会执着于这一门语言.论速度的话,c那系更好一些,而且对底层的操控更多是c那边的.还是想通过Java做这些事. 对Java不怎么懂,它的底层实现是怎样的.只知道一个大体的思想,不知道具体步骤. ...

  9. Confluence 6 Oracle 创建数据库用户

    创建用户后并且指派权限: 使用 sqlplus 命令行工具通过命令行来访问 Oracle sqlplus user/password <as sysdba|as sysoper> 如果你的 ...

  10. Java与C++&C语言的个人看法----异同点(A)

    日期:2018.7.30 星期一 博客期:004 第四期的博客我来说一下自己对Java的看法以及它与C++有什么异同之处! 先说不同之处吧!Java应该说是更面向对象一点,它的Java包里类可以通过用 ...