树链剖分-模板题 HAOI2015
Posted 1218ghcred
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树链剖分-模板题 HAOI2015相关的知识,希望对你有一定的参考价值。
1 #include <stdio.h> 2 #include <vector> 3 4 using namespace std; 5 6 typedef long long LL; 7 8 const int _N = 1000000; 9 10 vector<LL> G[_N]; 11 LL Size[_N], ID[_N], Anc[_N], Hson[_N], D[_N], Dad[_N], A[_N]; 12 LL Seg_root, Seg_cnt, L[_N], R[_N], Sum[_N], Lazy[_N];//segt 13 LL N, ID_cnt; 14 15 void Find(LL node, LL dad, LL deep) 16 { 17 LL mx = -1; 18 Size[node] = 1, D[node] = deep, Dad[node] = dad; 19 for (LL i = 0; i != G[node].size(); ++i) { 20 LL v = G[node][i]; 21 if (v == dad) continue; 22 Find(v, node, deep + 1), Size[node] += Size[v]; 23 if (mx == -1 || Size[G[node][mx]] < Size[v]) mx = i; 24 } 25 if (mx != -1) Hson[node] = G[node][mx]; 26 return; 27 } 28 29 void Connect(LL node, LL anc) 30 { 31 ID[node] = ++ID_cnt, Anc[node] = anc; 32 if (Hson[node]) Connect(Hson[node], anc); 33 for (LL i = 0; i != G[node].size(); ++i) { 34 LL v = G[node][i]; 35 if (v == Dad[node] || v == Hson[node]) continue; 36 Connect(v, v); 37 } 38 return; 39 } 40 41 void Seg_PD(LL &p, LL l, LL r) 42 { 43 if (l == r) { Lazy[p] = 0; return; } 44 45 if (!L[p]) L[p] = ++Seg_cnt; 46 if (!R[p]) R[p] = ++Seg_cnt; 47 LL mid = l+r >> 1; 48 Sum[L[p]] += Lazy[p] * (mid-l+1), Lazy[L[p]] += Lazy[p]; 49 Sum[R[p]] += Lazy[p] * (r-mid), Lazy[R[p]] += Lazy[p]; 50 Lazy[p] = 0; 51 return; 52 } 53 54 void Seg_Add(LL &p, LL l, LL r, LL s, LL t, LL d) 55 { 56 if (!p) p = ++Seg_cnt; 57 if (s <= l && r <= t) { Sum[p] += d * (r-l+1), Lazy[p] += d; return; } 58 LL mid = l+r >> 1; 59 if (Lazy[p]) Seg_PD(p, l, r); 60 if (s <= r && t > mid) Seg_Add(R[p], mid+1, r, s, t, d); 61 if (s <= mid && t >= l) Seg_Add(L[p], l, mid, s, t, d); 62 Sum[p] = Sum[R[p]] + Sum[L[p]]; 63 return; 64 } 65 66 LL Seg_Qry(LL &p, LL l, LL r, LL s, LL t) 67 { 68 if (!p) p = ++Seg_cnt; 69 if (s <= l && r <= t) return Sum[p]; 70 LL mid = l+r >> 1, sum = 0; 71 if (Lazy[p]) Seg_PD(p, l, r); 72 if (s <= r && t > mid) sum += Seg_Qry(R[p], mid+1, r, s, t); 73 if (s <= mid && t >= l) sum += Seg_Qry(L[p], l, mid, s, t); 74 return sum; 75 } 76 77 void Add_s(LL k, LL d) 78 { 79 Seg_Add(Seg_root, 1, N, ID[k], ID[k], d); 80 return; 81 } 82 83 void Add_r(LL k, LL d) 84 { 85 Seg_Add(Seg_root, 1, N, ID[k], ID[k] + Size[k] - 1, d); 86 return; 87 } 88 89 LL Qry(LL x, LL y) 90 { 91 LL sum = 0; 92 while (Anc[x] != Anc[y]) { 93 if (D[Anc[x]] < D[Anc[y]]) swap(x, y); 94 sum += Seg_Qry(Seg_root, 1, N, ID[Anc[x]], ID[x]); 95 x = Dad[Anc[x]]; 96 } 97 if (D[x] > D[y]) swap(x, y); 98 sum += Seg_Qry(Seg_root, 1, N, ID[x], ID[y]); 99 return sum; 100 } 101 102 int main_main() 103 { 104 LL M, i; 105 scanf("%lld%lld", &N, &M); 106 for (i = 1; i <= N; ++i) scanf("%lld", &A[i]); 107 for (i = 1; i < N; ++i) { 108 LL t1, t2; 109 scanf("%lld%lld", &t1, &t2); 110 G[t1].push_back(t2), G[t2].push_back(t1); 111 } 112 113 Find(1, -1218, 1); 114 Connect(1, 1); 115 for (i = 1; i <= N; ++i) Add_s(i, A[i]); 116 117 for (i = 1; i <= M; ++i) { 118 LL ins, t1, t2; 119 scanf("%lld%lld", &ins, &t1); 120 if (ins == 1) {//add_s 121 scanf("%lld", &t2); 122 Add_s(t1, t2); 123 } else if (ins == 2) {//add_r 124 scanf("%lld", &t2); 125 Add_r(t1, t2); 126 } else if (ins == 3) {//qry 127 printf("%lld\n", Qry(1, t1)); 128 } 129 } 130 return 0; 131 } 132 133 const int main_stack=16; 134 char my_stack[128<<20]; 135 int main() { 136 __asm__("movl %%esp, (%%eax);\n"::"a"(my_stack):"memory"); 137 __asm__("movl %%eax, %%esp;\n"::"a"(my_stack+sizeof(my_stack)-main_stack):"%esp"); 138 main_main(); 139 __asm__("movl (%%eax), %%esp;\n"::"a"(my_stack):"%esp"); 140 return 0; //add stack copy copy!!! 141 }
敲了一个树剖模板,顺便复习了一下动态开点的线段树.
NKOJ需要扩栈!
题目
【HAOI2015】树上操作 | ||
|
问题描述
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
输入格式
第一行包含两个整数 N, M 。表示点数和操作数。
接下来一行 N 个整数,表示树中节点的初始权值。
接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。
再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操
作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
输出格式
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
样例输入
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
样例输出
6
9
13
提示
对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不会超过 10^6 。
以上是关于树链剖分-模板题 HAOI2015的主要内容,如果未能解决你的问题,请参考以下文章
P3178 [HAOI2015]树上操作 (树链剖分模版题)