这个题感觉很厉害的样子。。

首先我们注意到一点:每次加的 $d$ 都是非负的。

那么就说明一个数只可能从负数变成非负数并且只会变一次。

所以我们就可以暴力地去改变一个数的正负情况。

然后我们就可以用树链剖分,维护一下区间的最大负数和负数的个数就可以了。

时间复杂度 $O(n\log^2 n)$,空间复杂度 $O(n)$。

  1. #include <cstdio>
  2. typedef long long LL;
  3. #define N 262144 + 5
  4. #define INF 1234567890987654321LL
  5.  
  6. int n, m, tot, cnt, A[N], Head[N], Root[N], Fa[N], Ad[N], Pos[N], Num[N], Dfn[N], Len[N], Size[N], Son[N], q[N];
  7.  
  8. struct Edge
  9. {
  10. int next, node;
  11. }E[N];
  12.  
  13. struct Segment_Tree
  14. {
  15. int l, r, neg_cnt;
  16. LL sum, delta, neg_Max;
  17. }h[N];
  18.  
  19. inline void addedge(int u, int v)
  20. {
  21. E[++ tot].next = Head[u], Head[u] = tot;
  22. E[tot].node = v;
  23. E[++ tot].next = Head[v], Head[v] = tot;
  24. E[tot].node = u;
  25. }
  26.  
  27. inline LL Abs(LL x)
  28. {
  29. return x > ? x : -x;
  30. }
  31.  
  32. inline void dfs(int z)
  33. {
  34. Size[z] = ;
  35. for (int i = Head[z]; i; i = E[i].next)
  36. {
  37. int d = E[i].node;
  38. if (d == Fa[z]) continue ;
  39. Fa[d] = z;
  40. dfs(d);
  41. Size[z] += Size[d];
  42. }
  43. for (int i = Head[z]; i; i = E[i].next)
  44. {
  45. int d = E[i].node;
  46. if (d == Fa[z]) continue ;
  47. if (!Son[z] || Size[d] > Size[Son[z]])
  48. Son[z] = d;
  49. }
  50. }
  51.  
  52. inline void update(int x)
  53. {
  54. h[x].sum = h[h[x].l].sum + h[h[x].r].sum;
  55. h[x].neg_Max = h[h[x].l].neg_Max > h[h[x].r].neg_Max ? h[h[x].l].neg_Max : h[h[x].r].neg_Max;
  56. h[x].neg_cnt = h[h[x].l].neg_cnt + h[h[x].r].neg_cnt;
  57. }
  58.  
  59. inline void Build(int &x, int l, int r)
  60. {
  61. if (!x) x = ++ tot;
  62. if (l == r)
  63. {
  64. h[x].sum = Abs(A[q[l]]);
  65. if (A[q[l]] < ) h[x].neg_Max = A[q[l]], h[x].neg_cnt = ;
  66. else h[x].neg_Max = -INF;
  67. return ;
  68. }
  69. int mid = l + r >> ;
  70. Build(h[x].l, l, mid);
  71. Build(h[x].r, mid + , r);
  72. update(x);
  73. }
  74.  
  75. inline void apply(int x, int l, int r, LL d)
  76. {
  77. h[x].sum += d * (r - l + - h[x].neg_cnt * );
  78. h[x].delta += d;
  79. h[x].neg_Max += d;
  80. }
  81.  
  82. inline void push(int x, int l, int r)
  83. {
  84. if (h[x].delta)
  85. {
  86. int mid = l + r >> ;
  87. apply(h[x].l, l, mid, h[x].delta);
  88. apply(h[x].r, mid + , r, h[x].delta);
  89. h[x].delta = ;
  90. }
  91. }
  92.  
  93. inline void Point_Modify(int x, int l, int r, LL d)
  94. {
  95. if (l == r)
  96. {
  97. h[x].sum = -h[x].sum;
  98. h[x].neg_Max = -INF;
  99. h[x].neg_cnt = ;
  100. return ;
  101. }
  102. int mid = l + r >> ;
  103. push(x, l, r);
  104. if (h[h[x].l].neg_Max > h[h[x].r].neg_Max)
  105. Point_Modify(h[x].l, l, mid, d);
  106. else Point_Modify(h[x].r, mid + , r, d);
  107. update(x);
  108. }
  109.  
  110. inline void Modify(int x, int l, int r, int s, int t, LL d)
  111. {
  112. if (l == s && r == t)
  113. {
  114. while (h[x].neg_Max >= -d)
  115. Point_Modify(x, l, r, d);
  116. apply(x, l, r, d);
  117. return ;
  118. }
  119. push(x, l, r);
  120. int mid = l + r >> ;
  121. if (t <= mid) Modify(h[x].l, l, mid, s, t, d);
  122. else if (s > mid) Modify(h[x].r, mid + , r, s, t, d);
  123. else Modify(h[x].l, l, mid, s, mid, d), Modify(h[x].r, mid + , r, mid + , t, d);
  124. update(x);
  125. }
  126.  
  127. inline LL Query(int x, int l, int r, int s, int t)
  128. {
  129. if (l == s && r == t) return h[x].sum;
  130. push(x, l, r);
  131. int mid = l + r >> ;
  132. if (t <= mid) return Query(h[x].l, l, mid, s, t);
  133. else if (s > mid) return Query(h[x].r, mid + , r, s, t);
  134. else return Query(h[x].l, l, mid, s, mid) + Query(h[x].r, mid + , r, mid + , t);
  135. }
  136.  
  137. inline void Prepare()
  138. {
  139. tot = ;
  140. for (int i = ; i <= n; i ++)
  141. {
  142. if (Ad[i]) continue ;
  143. Dfn[i] = Dfn[Fa[i]] + ;
  144. q[] = ;
  145. cnt ++;
  146. for (int x = i; x; x = Son[x])
  147. {
  148. Ad[x] = i, Pos[x] = ++ Len[cnt];
  149. Num[x] = cnt, Dfn[x] = Dfn[i];
  150. q[++ q[]] = x;
  151. }
  152. Build(Root[cnt], , Len[cnt]);
  153. }
  154. }
  155.  
  156. int main()
  157. {
  158. #ifndef ONLINE_JUDGE
  159. freopen("4127.in", "r", stdin);
  160. freopen("4127.out", "w", stdout);
  161. #endif
  162.  
  163. scanf("%d%d", &n, &m);
  164. for (int i = ; i <= n; i ++)
  165. scanf("%d", A + i);
  166. for (int i = , u, v; i < n; i ++)
  167. {
  168. scanf("%d%d", &u, &v);
  169. addedge(u, v);
  170. }
  171. dfs();
  172. Prepare();
  173. for (int op, u, v; m; m --)
  174. {
  175. scanf("%d", &op);
  176. if (op == )
  177. {
  178. LL d;
  179. scanf("%d%d%lld", &u, &v, &d);
  180. if (Dfn[u] < Dfn[v]) u = u - v, v = u + v, u = v - u;
  181. for (; Dfn[u] > Dfn[v]; u = Fa[Ad[u]])
  182. Modify(Root[Num[u]], , Len[Num[u]], , Pos[u], d);
  183. for (; Ad[u] != Ad[v]; u = Fa[Ad[u]], v = Fa[Ad[v]])
  184. {
  185. Modify(Root[Num[u]], , Len[Num[u]], , Pos[u], d);
  186. Modify(Root[Num[v]], , Len[Num[v]], , Pos[v], d);
  187. }
  188. if (Pos[u] > Pos[v]) u = u - v, v = u + v, u = v - u;
  189. Modify(Root[Num[u]], , Len[Num[u]], Pos[u], Pos[v], d);
  190. }
  191. else
  192. {
  193. scanf("%d%d", &u, &v);
  194. LL ans = ;
  195. if (Dfn[u] < Dfn[v]) u = u - v, v = u + v, u = v - u;
  196. for (; Dfn[u] > Dfn[v]; u = Fa[Ad[u]])
  197. ans += Query(Root[Num[u]], , Len[Num[u]], , Pos[u]);
  198. for (; Ad[u] != Ad[v]; u = Fa[Ad[u]], v = Fa[Ad[v]])
  199. {
  200. ans += Query(Root[Num[u]], , Len[Num[u]], , Pos[u]);
  201. ans += Query(Root[Num[v]], , Len[Num[v]], , Pos[v]);
  202. }
  203. if (Pos[u] > Pos[v]) u = u - v, v = u + v, u = v - u;
  204. ans += Query(Root[Num[u]], , Len[Num[u]], Pos[u], Pos[v]);
  205. printf("%lld\n", ans);
  206. }
  207. }
  208.  
  209. #ifndef ONLINE_JUDGE
  210. fclose(stdin);
  211. fclose(stdout);
  212. #endif
  213. return ;
  214. }

4127_Gromah

BZOJ 4127 Abs 解题报告的更多相关文章

  1. bzoj 4127: Abs 树链剖分

    4127: Abs Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 11  Solved: 5[Submit][Status][Discuss] Des ...

  2. BZOJ[4127] Abs

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=4127 不算难的样子,才见过此类模型. 首先可以发现每次修改只增不减,那么这$O(n)$的负数最 ...

  3. BZOJ 2959: 长跑 解题报告

    2959: 长跑 Description 某校开展了同学们喜闻乐见的阳光长跑活动.为了能"为祖国健康工作五十年",同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑 ...

  4. BZOJ 4238 电压 解题报告

    BZOJ 4238 电压 考虑一条边成为答案以后,删去Ta后剩下的图是一个或很多个二分图,即没有奇环 则一条边可以成为答案,当且仅当自己在所有奇环的交上且不在偶环上. 考虑建出dfs树,那么返祖边一定 ...

  5. BZOJ 3159: 决战 解题报告

    BZOJ 3159: 决战 1 sec 512MB 题意: 给你一颗\(n\)个点,初始点权为\(0\)的有跟树,要求支持 Increase x y w 将路径\(x\)到\(y\)所有点点权加上\( ...

  6. BZOJ 3328: PYXFIB 解题报告

    BZOJ 3328: PYXFIB 题意 给定\(n,p,k(1\le n\le 10^{18},1\le k\le 20000,1\le p\le 10^9,p \ is \ prime,k|(p- ...

  7. BZOJ 4302 Buildings 解题报告

    这个题好像很有趣的样子. 题目分析: 房间都是 $1\times k$ 的,也就是一条一条的.这个好像比较显然的样子. 一个房间如果要覆盖某个格子$u$,那么这个房间的面积至少为 $dis(u, Bo ...

  8. BZOJ 3160 万径人踪灭 解题报告

    这个题感觉很神呀.将 FFT 和 Manacher 有机结合在了一起. 首先我们不管那个 “不能连续” 的条件,那么我们就可以求出有多少对字母关于某一条直线对称,然后记 $T_i$ 为关于直线 $i$ ...

  9. BZOJ 3953 Self-Assembly 解题报告

    首先,我们可以先考虑一个暴力一点的算法: 对于任意两个分子,如果它们能以至少一种进行匹配,那么我们就在这两个分子之间连一条边. 然后如果我们能找到一个环,就说明是 unbounded,否则就是 bou ...

随机推荐

  1. Redis 命令 - Hashs

    HDEL key field [field ...] Delete one or more hash fields 127.0.0.1:6379> HSET book.1 title hello ...

  2. 理解CPU内存管理

    概述:从设计层面理解CPU的内存模式,包括段式内存管理.页式内存管理以及虚拟化扩展内存管理.实际上,硬件支持与软件实现从来就不是能分开讲的,比如,Intel CPU架构师在选择CPU的硬件特性时,必然 ...

  3. inline-block元素的一些坑

    当年刚知道CSS display有 inline-block 这个神奇的属性的时候,感觉碉堡了,以为从此不用float了,什么div.p,只要 display: inline-block 就在一行上了 ...

  4. uva673 - Parentheses Balance(栈)

    题意:1.空串合法.2.若A和B合法,则AB合法.3.若A合法,则(A)和[A]合法. 思路:遍历串,遇到(或[,则压入队列,若遇到),判断:若栈空,则不合法:若栈顶元素不是(,也不合法.]同理.因为 ...

  5. CMakeLists实战解读--YouCompleteMe

    原文转载自:Ricky.K http://www.cnblogs.com/rickyk/p/3877238.html 个人一直有一个想法,就是想出一系列关于CMakeLists.txt国外经典例子的实 ...

  6. Android 源码编译 步骤

    添加资源后编译步骤 1:lunch 112:mmm frameworks/base/core/res/生成Install: out/target/product/hammerhead/system/f ...

  7. input内容改变触发事件,兼容IE

    <html> <head> <script type="text/javascript"> window.onload = function() ...

  8. [DevExpress][TreeList]条件隐藏节点CheckBox

    关键代码: /// <summary> /// 隐藏CheckBox /// 说明 /// 在CustomDrawNodeCheckBox事件中使用 /// eg: /// TreeLis ...

  9. 防止非授权用户调用DLL

    1.首先要创建一个密钥文件(*.snk)

  10. wordpress在Linux nginx下权限设置

    1.wordpress 权限对安装和使用效果的影响很大:权限错误将影响theme的安装:不能安装theme或者修改theme或删除theme. 相关设置:  chmod 755 wordpress f ...