博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[BZOJ4034] [HAOI2015] T2 (树链剖分)
阅读量:5039 次
发布时间:2019-06-12

本文共 4073 字,大约阅读时间需要 13 分钟。

Description

  有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:
  操作 1 :把某个节点 x 的点权增加 a 。
  操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
  操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

Input

  第一行包含两个整数 N, M 。表示点数和操作数。
  接下来一行 N 个整数,表示树中节点的初始权值。
  接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。
  再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操
  作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。

Output

  对于每个询问操作,输出该询问的答案。答案之间用换行隔开。 

Sample Input

5 5
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3

Sample Output

6
9
13

HINT

  对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不会超过 10^6 。

Source

  

Solution

  树链剖分,用线段树维护点权;对子树的修改就是区间修改,因为其dfs序是连续的

1 #include 
2 using namespace std; 3 struct edge 4 { 5 int v, nxt; 6 }e[200005]; 7 struct point 8 { 9 int val, siz, fa, son, dfn, top; 10 }p[100005]; 11 struct seg 12 { 13 long long val, lazy; 14 }a[300005]; 15 int fst[100005], ptot; 16 17 void addedge(int i, int u, int v) 18 { 19 e[i] = (edge){v, fst[u]}, fst[u] = i; 20 } 21 22 void DFS1(int u) 23 { 24 p[u].siz = 1; 25 for(int i = fst[u]; i; i = e[i].nxt) 26 if(p[u].fa != e[i].v) 27 { 28 p[e[i].v].fa = u; 29 DFS1(e[i].v); 30 p[u].siz += p[e[i].v].siz; 31 if(p[e[i].v].siz > p[p[u].son].siz) 32 p[u].son = e[i].v; 33 } 34 } 35 36 void DFS2(int u, int top) 37 { 38 p[u].dfn = ++ptot, p[u].top = top; 39 if(p[u].son) DFS2(p[u].son, top); 40 for(int i = fst[u]; i; i = e[i].nxt) 41 if(e[i].v != p[u].fa && e[i].v != p[u].son) 42 DFS2(e[i].v, e[i].v); 43 } 44 45 void push_up(int o, int l, int r) 46 { 47 a[o].val = a[o << 1].val + a[o << 1 | 1].val; 48 a[o].val += a[o].lazy * (r - l + 1); 49 } 50 51 void push_down(int o, int l, int r) 52 { 53 int mid = (l + r) >> 1; 54 if(l == r) return; 55 if(a[o].lazy) 56 { 57 a[o << 1].lazy += a[o].lazy; 58 a[o << 1].val += a[o].lazy * (mid - l + 1); 59 a[o << 1 | 1].lazy += a[o].lazy; 60 a[o << 1 | 1].val += a[o].lazy * (r - mid); 61 a[o].lazy = 0; 62 } 63 } 64 65 void update(int o, int l, int r, int ql, int qr, int val) 66 { 67 int mid = (l + r) >> 1; 68 push_down(o, l, r); 69 if(ql <= l && r <= qr) 70 { 71 a[o].lazy += val; 72 a[o].val += (long long)val * (r - l + 1); 73 return; 74 } 75 if(ql <= mid) update(o << 1, l, mid, ql, qr, val); 76 if(mid < qr) update(o << 1 | 1, mid + 1, r, ql, qr, val); 77 push_up(o, l, r); 78 } 79 80 long long query(int o, int l, int r, int ql, int qr) 81 { 82 int mid = (l + r) >> 1; 83 long long ans = 0; 84 push_down(o, l, r); 85 if(ql <= l && r <= qr) return a[o].val; 86 if(ql <= mid) ans = query(o << 1, l, mid, ql, qr); 87 if(mid < qr) ans += query(o << 1 | 1, mid + 1, r, ql, qr); 88 return ans; 89 } 90 91 int main() 92 { 93 int n, m, u, v, op, x, val; 94 long long ans; 95 scanf("%d%d", &n, &m); 96 for(int i = 1; i <= n; ++i) 97 scanf("%d", &p[i].val); 98 for(int i = 1; i < n; ++i) 99 {100 scanf("%d%d", &u, &v);101 addedge(i << 1, u, v);102 addedge(i << 1 | 1, v, u);103 }104 DFS1(1), DFS2(1, 1);105 for(int i = 1; i <= n; ++i)106 update(1, 1, n, p[i].dfn, p[i].dfn, p[i].val);107 while(m--)108 {109 scanf("%d", &op);110 if(op == 1)111 {112 scanf("%d%d", &x, &val);113 update(1, 1, n, p[x].dfn, p[x].dfn, val);114 }115 else if(op == 2)116 {117 scanf("%d%d", &x, &val);118 update(1, 1, n, p[x].dfn, p[x].dfn + p[x].siz - 1, val);119 }120 else121 {122 scanf("%d", &x);123 ans = 0;124 while(x)125 {126 ans += query(1, 1, n, p[p[x].top].dfn, p[x].dfn);127 x = p[p[x].top].fa;128 }129 printf("%lld\n", ans);130 }131 }132 return 0;133 }
View Code

 

转载于:https://www.cnblogs.com/CtrlCV/p/5619362.html

你可能感兴趣的文章
lua基金会【五岁以下儿童】I/O文件操作
查看>>
一个小的日常实践——高速Fibonacci数算法
查看>>
创建与删除索引
查看>>
java的基本数据类型
查看>>
机器学些技法(9)--Decision Tree
查看>>
静态页面复习--用semantic UI写一个10min首页
查看>>
在Windows下安装64位压缩包版mysql 5.7.11版本的方法
查看>>
drf权限组件
查看>>
输入月份和日期,得出是今年第几天
查看>>
利用mysqldump备份mysql
查看>>
Qt中子窗口全屏显示与退出全屏
查看>>
使用brew安装软件
查看>>
[BZOJ1083] [SCOI2005] 繁忙的都市 (kruskal)
查看>>
吴裕雄 python 机器学习——数据预处理嵌入式特征选择
查看>>
Centos6.4安装JDK
查看>>
201521123069 《Java程序设计》 第4周学习总结
查看>>
线性表的顺序存储——线性表的本质和操作
查看>>
【linux】重置fedora root密码
查看>>
用swing做一个简单的正则验证工具
查看>>
百度坐标(BD-09)、国测局坐标(火星坐标,GCJ-02)和WGS-84坐标互转
查看>>