题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4034

题意:中文题面

思路:树链剖分入门题。 剖分后就是一个简单的区间更新和区间求和问题。用线段树去维护一下。 由于有一个操作是关于子树的,可以用DFS序来求,但是由于剖分后的序列都是连续的,所以只需要记录下返回当前根时前一个点的位置即可进行子树操作。

  1. #define _CRT_SECURE_NO_DEPRECATE
  2. #include<iostream>
  3. #include<cstring>
  4. #include<string>
  5. #include<algorithm>
  6. #include<stdio.h>
  7. #include<queue>
  8. #include<vector>
  9. #include<stack>
  10. #include<map>
  11. #include<set>
  12. #include<time.h>
  13. #include<cmath>
  14. #include<sstream>
  15. #include<assert.h>
  16. using namespace std;
  17. #define L(x) x<<1
  18. #define R(x) x<<1|1
  19. typedef long long int LL;
  20. const int inf = 0x3f3f3f3f;
  21. const LL INF = 0x3f3f3f3f3f3f3f3fLL;
  22. const int MAXN = + ;
  23. int val[MAXN], head[MAXN], tot, cnt;
  24. struct Edge{
  25. int to,next;
  26. Edge(int _to = , int _next = ) :to(_to), next(_next){};
  27. }Edges[MAXN * ];
  28. void add(int u, int v){
  29. Edges[tot].to = v;
  30. Edges[tot].next = head[u];
  31. head[u] = tot++;
  32. }
  33. int id[MAXN], endid[MAXN], son[MAXN], deep[MAXN], size[MAXN], fa[MAXN], reid[MAXN], top[MAXN];
  34. void Init(){
  35. tot = ; cnt = ;
  36. memset(head, -, sizeof(head));
  37. memset(son, -, sizeof(son));
  38. }
  39. void DFS1(int u, int p,int dep){
  40. fa[u] = p; size[u] = ; deep[u] = dep;
  41. for (int i = head[u]; i != -; i = Edges[i].next){
  42. if (Edges[i].to != p){
  43. DFS1(Edges[i].to, u,dep+);
  44. size[u] += size[Edges[i].to];
  45. if (son[u] == - || size[Edges[i].to] > size[son[u]]){
  46. son[u] = Edges[i].to;
  47. }
  48. }
  49. }
  50. }
  51. void DFS2(int u, int tp){
  52. id[u] = ++cnt; reid[id[u]] = u; top[u] = tp;
  53. if (son[u] == -){
  54. endid[u] = cnt;
  55. return;
  56. }
  57. DFS2(son[u], tp);
  58. for (int i = head[u]; i != -; i = Edges[i].next){
  59. if (son[u] != Edges[i].to&&Edges[i].to != fa[u]){
  60. DFS2(Edges[i].to, Edges[i].to);
  61. }
  62. }
  63. endid[u] = cnt;
  64. }
  65. struct Node{
  66. int st, ed;
  67. LL sum, lazy;
  68. }Seg[MAXN * ];
  69. void Build(int l, int r, int k){
  70. Seg[k].st = l; Seg[k].ed = r; Seg[k].lazy = ;
  71. if (l == r){
  72. Seg[k].sum = val[reid[l]];
  73. return;
  74. }
  75. int mid = (l + r) / ;
  76. Build(l, mid, L(k)); Build(mid + , r, R(k));
  77. Seg[k].sum = Seg[L(k)].sum + Seg[R(k)].sum;
  78. }
  79. void pushUp(int k){
  80. Seg[k].sum = Seg[L(k)].sum + Seg[R(k)].sum;
  81. }
  82. void pushDown(int k){
  83. if (Seg[k].lazy){
  84. Seg[L(k)].sum += 1LL*Seg[k].lazy*(Seg[L(k)].ed - Seg[L(k)].st + );
  85. Seg[L(k)].lazy += Seg[k].lazy;
  86. Seg[R(k)].sum += 1LL*Seg[k].lazy*(Seg[R(k)].ed - Seg[R(k)].st + );
  87. Seg[R(k)].lazy += Seg[k].lazy;
  88. Seg[k].lazy = ;
  89. }
  90. }
  91. void Add(int l, int r, int k,int val){
  92. if (Seg[k].st == l&&Seg[k].ed == r){
  93. Seg[k].lazy += val;
  94. Seg[k].sum += 1LL * val * (r - l + );
  95. return;
  96. }
  97. pushDown(k);
  98. if (r <= Seg[L(k)].ed){
  99. Add(l, r, L(k),val);
  100. }
  101. else if (l >= Seg[R(k)].st){
  102. Add(l, r, R(k),val);
  103. }
  104. else{
  105. Add(l, Seg[L(k)].ed, L(k), val);
  106. Add(Seg[R(k)].st, r, R(k), val);
  107. }
  108. pushUp(k);
  109. }
  110. LL Query(int l, int r, int k){
  111. if (Seg[k].st == l&&Seg[k].ed == r){
  112. return Seg[k].sum;
  113. }
  114. pushDown(k);
  115. LL sum = ;
  116. if (r <= Seg[L(k)].ed){
  117. sum=Query(l, r, L(k));
  118. }
  119. else if (l >= Seg[R(k)].st){
  120. sum=Query(l, r, R(k));
  121. }
  122. else{
  123. sum=Query(l, Seg[L(k)].ed, L(k)) + Query(Seg[R(k)].st, r, R(k));
  124. }
  125. pushUp(k);
  126. return sum;
  127. }
  128. LL Query(int x){
  129. LL ans = ;
  130. while (top[x]!=){
  131. ans += Query(id[top[x]], id[x],);
  132. x = fa[top[x]];
  133. }
  134. ans += Query(,id[x], );
  135. return ans;
  136. }
  137. int main(){
  138. //#ifdef kirito
  139. // freopen("in.txt", "r", stdin);
  140. // freopen("out.txt", "w", stdout);
  141. //#endif
  142. // int start = clock();
  143. int n, m;
  144. while (~scanf("%d%d",&n,&m)){
  145. Init();
  146. for (int i = ; i <= n; i++){
  147. scanf("%d", &val[i]);
  148. }
  149. for (int i = ; i < n; i++){
  150. int u, v;
  151. scanf("%d%d", &u, &v);
  152. add(u, v); add(v, u);
  153. }
  154. DFS1(, , ); DFS2(, );
  155. Build(, n, );
  156. while (m--){
  157. int ope, x, a;
  158. scanf("%d", &ope);
  159. switch (ope)
  160. {
  161. case :scanf("%d%d", &x, &a); Add(id[x],id[x] , , a); break;
  162. case :scanf("%d%d", &x, &a); Add(id[x], endid[x], , a); break;
  163. default: scanf("%d", &x); printf("%lld\n", Query(x)); break;
  164. }
  165. }
  166. }
  167. //#ifdef LOCAL_TIME
  168. // cout << "[Finished in " << clock() - start << " ms]" << endl;
  169. //#endif
  170. return ;
  171. }

BZOJ 4034 树链剖分的更多相关文章

  1. BZOJ 4326 树链剖分+二分+差分+记忆化

    去年NOIP的时候我还不会树链剖分! 还是被UOJ 的数据卡了一组. 差分的思想还是很神啊! #include <iostream> #include <cstring> #i ...

  2. BZOJ 1036 && 树链剖分

    还是太弱啊..各种数据结构只听过名字却没有一点概念..树链剖分也在这个范畴..今天来进一步深化一下教育改革推进全民素质提高. 性质 忘了在哪里看到的一篇blog有一句话讲得非常好,树链剖分不是一种数据 ...

  3. bzoj 3083 树链剖分

    首先我们先将树提出一个根变成有根树,那么我们可以通过树链剖分来实现对于子树的最小值求解,那么按照当前的根和询问的点的相对位置关系我们可以将询问变成某个子树和或者除去某颗子树之后其余的和,前者直接询问区 ...

  4. bzoj 2243 树链剖分

    2013-11-19 16:21 原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=2243 树链剖分,用线段树记录该区间的颜色段数,左右端点颜 ...

  5. bzoj 4196 树链剖分 模板

    [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2135  Solved: 1232[Submit][Status][D ...

  6. BZOJ 4811 树链剖分+线段树

    思路: 感觉这题也可神了.. (还是我太弱) 首先发现每一位不会互相影响,可以把每一位分开考虑,然后用树链剖分或者LCT维护这个树 修改直接修改,询问的时候算出来每一位填0,1经过这条链的变换之后得到 ...

  7. BZOJ 2286 树链剖分+DFS序+虚树+树形DP

    第一次学习虚树,就是把无关的点去掉.S里维护一条链即可. #include <iostream> #include <cstring> #include <cstdio& ...

  8. BZOJ 3083 树链剖分+倍增+线段树

    思路: 先随便选个点 链剖+线段树 1操作 就直接改root变量的值 2操作 线段树上改 3操作 分成三种情况 1.new root = xx 整个子树的min就是ans 2. lca(new roo ...

  9. BZOJ 2836 树链剖分+线段树

    思路: 链剖+线段树裸题 重链的标号就是DFS序 所以查子树的时候每回就 query(change[x],change[x]+size[x]-1) 就好了 剩下的应该都会吧.. //By Sirius ...

随机推荐

  1. Sublime-Text macOS 编译运行armadillo

    { "cmd" : ["g++ -std=c++14 -Wall -larmadillo -framework Accelerate ${file_name} -o ${ ...

  2. Prometheus + Node Exporter + Grafana 监控主机运行信息

      上一篇文章中讲了如何利用Prometheus和Grafana监控SpringBoot应用的JVM信息,这次就来看看如何监控 服务器运行状态,先列出用到的工具: Prometheus node_ex ...

  3. 迁移数据时 timestamp类型字段报错: 1067 - Invalid default value for 'login_time'

    MySQL数据库升级 8.0.13,原版本5.5:执行导出来的SQL文件时报错 1067 - Invalid default value for 'login_time' 原因:MySQL 5.6以后 ...

  4. iOS多媒体总结&进入后台播放音乐

    1. 播放mp3需要导入框架,AVFoundation支持音频文件(.caf..aif..wav..wmv和.mp3)的播放. #import <AVFoundation/AVFoundatio ...

  5. [design pattern](0) 概述

    一 引语 大家好,这是我第一次在网上写文章.从学校毕业一年多,感觉还有很多东西需要去学习.最近正在学习设计模式,希望可以在博客园把我学习的知识记录下来,能够和大家一起讨论设计模式相关的话题,也希望这个 ...

  6. UltraISO 9.6.1.3016(带注册机)

    UltraISO 9.6.1.3016 链接: http://pan.baidu.com/s/1kTqO6hD密码: ehdc

  7. 知道css有个content属性吗?有什么作用?有什么应用?

    css的content属性专门应用在 before/after 伪元素上,用来插入生成内容.最常见的应用是利用伪类清除浮动. //一种常见利用伪类清除浮动的代码 .clearfix:after { c ...

  8. Spring cloud gateway自定义filter以及负载均衡

    自定义全局filter package com.example.demo; import java.nio.charset.StandardCharsets; import org.apache.co ...

  9. ADFS 2016 & Dynamics CRM

    参考:https://blog.csdn.net/vic0228/article/details/80188291 webapp 获取token https://adfs.demo.local/adf ...

  10. php不支持多线程怎么办

    PHP 默认并不支持多线程,要使用多线程需要安装 pthread 扩展,而要安装 pthread 扩展,必须使用 --enable-maintainer-zts 参数重新编译 PHP,这个参数是指定编 ...