再搬运:
关于树剖的具体内容上,传送门:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html(非常之详细)
链剖完,线段树上维护的是段最大以及段和即可,操作是点修改。
但是要注意有负数的情况!!!蒟蒻没看到WA了7、8次。。。蒟蒻就是弱,树剖竟然要写三天。。。买块豆腐去撞死吧
时间竟然有2500+MS,不过把许多大神踩在下面了,感觉挺好。。
上代码,感觉写的还不错啊,思路蛮清晰的:
1 #include <cstdlib> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <iostream> 6 #include <algorithm> 7 8 #define rep(i, n) for (int (i) = 1; (i) <= (n); ++(i)) 9 using namespace std; 10 11 struct edge{ 12 int next, to; 13 } e[100000]; 14 15 struct tree{ 16 int fa, son, size, w, dep, top, where; 17 } tr[100000]; 18 19 struct segment_tree{ 20 int sum, max; 21 } seg[100000]; 22 23 int n, tot, first[100000], size, t, lx, ry; 24 25 void add_Edge(int x, int y){ 26 e[++tot].next = first[x]; 27 first[x] = tot; 28 e[tot].to = y; 29 } 30 31 void add_edge(int x, int y){ 32 add_Edge(x, y); 33 add_Edge(y, x); 34 } 35 36 void make_tree(int p){ 37 int y; 38 tr[p].size = 1; 39 tr[p].son = 0; 40 for (int x = first[p]; x != 0; x = e[x].next){ 41 y = e[x].to; 42 if (y != tr[p].fa){ 43 tr[y].dep = tr[p].dep + 1; 44 tr[y].fa = p; 45 make_tree(y); 46 if (tr[p].son == 0 || tr[y].size > tr[tr[p].son].size) 47 tr[p].son = y; 48 tr[p].size += tr[y].size; 49 } 50 } 51 } 52 53 void fill_seg(int i){ 54 if (i >= size){ 55 seg[i].max = -30001; 56 seg[i].sum = -30001; 57 return; 58 } 59 fill_seg(i * 2); 60 fill_seg(i * 2 + 1); 61 seg[i].max = -30001; 62 seg[i].sum = seg[i * 2].sum * 2; 63 } 64 65 void change_value(int p, int v){ 66 int x = tr[p].where + size; 67 seg[x].max = v; 68 seg[x].sum = v; 69 while (x > 1){ 70 x >>= 1; 71 seg[x].max = max(seg[x * 2].max, seg[x * 2 + 1].max); 72 seg[x].sum = seg[x * 2].sum + seg[x * 2 + 1].sum; 73 } 74 } 75 76 void build_seg(int p){ 77 tr[p].where = ++t; 78 change_value(p, tr[p].w); 79 } 80 81 void make_seg(int p){ 82 if (tr[p].size == 1) return; 83 int s = tr[p].son, y; 84 tr[s].top = tr[p].top; 85 build_seg(s); 86 make_seg(s); 87 for (int x = first[p]; x != 0; x = e[x].next) 88 if ((y = e[x].to) != tr[p].fa && y != tr[p].son){ 89 tr[y].top = y; 90 build_seg(y); 91 make_seg(y); 92 } 93 } 94 95 int seg_max(int p, int l, int r){ 96 if (r < lx || l > ry) return -30001; 97 if (lx <= l && r <= ry) return seg[p].max; 98 int m = (l + r) >> 1; 99 int t1 = seg_max(p * 2, l, m), t2 = seg_max(p * 2 + 1, m + 1, r); 100 return max(t1, t2); 101 } 102 103 int tree_max(int x, int y){ 104 if (tr[x].top == tr[y].top){ 105 if (tr[x].dep > tr[y].dep) swap(x, y); 106 lx = tr[x].where; 107 ry = tr[y].where; 108 return seg_max(1, 1, size + 1); 109 } 110 if (tr[tr[x].top].dep < tr[tr[y].top].dep) swap(x, y); 111 lx = tr[tr[x].top].where; 112 ry = tr[x].where; 113 int t1 = seg_max(1, 1, size + 1), t2 = tree_max(tr[tr[x].top].fa, y); 114 return max(t1, t2); 115 } 116 117 int seg_sum(int p, int l, int r){ 118 if (r < lx || l > ry) return 0; 119 if (lx <= l && r <= ry) return seg[p].sum; 120 int m = (l + r) >> 1; 121 int t1 = seg_sum(p * 2, l, m), t2 = seg_sum(p * 2 + 1, m + 1, r); 122 return t1 + t2; 123 } 124 125 int tree_sum(int x, int y){ 126 if (tr[x].top == tr[y].top){ 127 if (tr[x].dep > tr[y].dep) swap(x, y); 128 lx = tr[x].where; 129 ry = tr[y].where; 130 return seg_sum(1, 1, size + 1); 131 } 132 if (tr[tr[x].top].dep < tr[tr[y].top].dep) swap(x, y); 133 lx = tr[tr[x].top].where; 134 ry = tr[x].where; 135 int t1 = seg_sum(1, 1, size + 1) , t2 = tree_sum(tr[tr[x].top].fa, y); 136 return t1 + t2; 137 } 138 139 int main(){ 140 scanf("%d", &n); 141 int x, y; 142 rep(i, n - 1){ 143 scanf("%d %d", &x, &y); 144 add_edge(x, y); 145 } 146 rep(i, n) 147 scanf("%d", &tr[i].w); 148 149 for (size = 1; size < n; size <<= 1); 150 --size; 151 152 tr[1].dep = 1; 153 make_tree(1); 154 tr[1].top = 1; 155 t = 0; 156 fill_seg(1); 157 build_seg(1); 158 make_seg(1); 159 160 int q, a; 161 scanf("%d", &q); 162 char C[10]; 163 while (q--){ 164 scanf("%s %d %d", C, &x, &y); 165 if (C[0] == 'C') 166 change_value(x, y); else 167 if (C[1] == 'M') 168 printf("%d ", tree_max(x, y)); else 169 if (C[1] == 'S') 170 printf("%d ", tree_sum(x, y)); 171 } 172 return 0; 173 }