1. 程式人生 > >hdu 3966 Aragorn's Story : 樹鏈剖分 O(nlogn)建樹 O((logn)²)修改與查詢

hdu 3966 Aragorn's Story : 樹鏈剖分 O(nlogn)建樹 O((logn)²)修改與查詢

esp style wow tree urn max return down data

  1 /**
  2 problem: http://acm.hdu.edu.cn/showproblem.php?pid=3966
  3 裸板
  4 **/
  5 #include<stdio.h>
  6 #include<stdlib.h>
  7 #include<string.h>
  8 #include<vector>
  9 using namespace std;
 10 
 11 const int MAXN = 500005;
 12 
 13 template <typename T>
 14
class SegmentTree { 15 private: 16 struct Node { 17 int left, right; 18 T sum, lazy; 19 } node[MAXN << 2]; 20 T data[MAXN]; 21 void pushUp(int root) { 22 node[root].sum = node[root << 1].sum + node[root << 1 | 1].sum; 23 }
24 void pushDown(int root) { 25 if(node[root].left == node[root].right) return; 26 int lson = root << 1; 27 int rson = root << 1 | 1; 28 node[lson].sum += node[root].lazy * (node[lson].right - node[lson].left + 1); 29 node[rson].sum += node[root].lazy * (node[rson].right - node[rson].left + 1
); 30 node[lson].lazy += node[root].lazy; 31 node[rson].lazy += node[root].lazy; 32 node[root].lazy = 0; 33 } 34 public: 35 void build(int left, int right, int root = 1) { 36 node[root].left = left; 37 node[root].right = right; 38 node[root].lazy = 0; 39 if(left == right) { 40 node[root].sum = data[left]; 41 } else { 42 int mid = (left + right) >> 1; 43 build(left, mid, root << 1); 44 build(mid + 1, right, root << 1 | 1); 45 pushUp(root); 46 } 47 } 48 void update(int left, int right, T value, int root = 1) { 49 int lson = root << 1; 50 int rson = root << 1 | 1; 51 node[root].sum += value * (right - left + 1); 52 if(node[root].left == left && node[root].right == right) { 53 node[root].lazy += value; 54 return ; 55 } 56 if(left >= node[rson].left) { 57 update(left, right, value, rson); 58 } else if(right <= node[lson].right) { 59 update(left, right, value, lson); 60 } else { 61 update(left, node[lson].right, value, lson); 62 update(node[rson].left, right, value, rson); 63 } 64 } 65 T query(int left, int right, int root = 1) { 66 int lson = root << 1; 67 int rson = root << 1 | 1; 68 if(node[root].lazy) pushDown(root); 69 if(node[root].left == left && node[root].right == right) { 70 return node[root].sum; 71 } 72 if(left >= node[rson].left) { 73 return query(left, right, rson); 74 } else if(right <= node[lson].right) { 75 return query(left, right, lson); 76 } else { 77 return query(left, node[lson].right, lson) + query(node[rson].left, right, rson); 78 } 79 } 80 void clear(int n, const vector<int> &d) { 81 for(int i = 1; i <= n; i ++) { 82 this->data[i] = d[i]; 83 } 84 build(1, n); 85 } 86 }; 87 88 template <typename T> 89 class TreeToLink { 90 private: 91 struct Point { 92 int size, son, depth, father, top, newId; 93 T data; 94 } point[MAXN]; 95 struct Edge { 96 int to, next; 97 } edge[MAXN << 1]; 98 int oldId[MAXN], first[MAXN], sign, sumOfPoint, cnt; 99 SegmentTree<T> st; 100 void dfs1(int u, int father = 0, int depth = 1) { 101 point[u].depth = depth; 102 point[u].father = father; 103 point[u].size = 1; 104 int maxson = -1; 105 for(int i = first[u]; i != -1; i = edge[i].next) { 106 int to = edge[i].to; 107 if(to == father) continue; 108 dfs1(to, u, depth + 1); 109 point[u].size += point[to].size; 110 if(point[to].size > maxson) { 111 point[u].son = to; 112 maxson = point[to].size; 113 } 114 } 115 } 116 void dfs2(int u, int top) { 117 point[u].newId = ++cnt; 118 oldId[cnt] = u; 119 point[u].top = top; 120 if(point[u].son == -1) { 121 return ; 122 } 123 dfs2(point[u].son, top); 124 for(int i = first[u]; i != -1; i = edge[i].next) { 125 int to = edge[i].to; 126 if(to == point[u].son || to == point[u].father) continue; 127 dfs2(to, to); 128 } 129 } 130 public: 131 void clear(int n) { 132 sumOfPoint = n; 133 sign = 0; 134 cnt = 0; 135 for(int i = 1; i <= n; i ++) { 136 first[i] = -1; 137 point[i].son = -1; 138 scanf("%d", &point[i].data); 139 } 140 } 141 void addEdgeOneWay(int u, int v) { 142 edge[sign].to = v; 143 edge[sign].next = first[u]; 144 first[u] = sign ++; 145 } 146 void addEdgeTwoWay(int u, int v) { 147 addEdgeOneWay(u, v); 148 addEdgeOneWay(v, u); 149 } 150 void preWork(int x = 1) { 151 dfs1(x); 152 dfs2(x, x); 153 vector<int> data(sumOfPoint + 1); 154 for(int i = 1; i <= sumOfPoint; i ++) { 155 data[i] = point[oldId[i]].data; 156 } 157 st.clear(sumOfPoint, data); 158 } 159 void updatePath(int x, int y, T z){ 160 while(point[x].top != point[y].top){ 161 if(point[point[x].top].depth < point[point[y].top].depth) 162 swap(x, y); 163 st.update(point[point[x].top].newId, point[x].newId, z); 164 x = point[point[x].top].father; 165 } 166 if(point[x].depth > point[y].depth) 167 swap(x, y); 168 st.update(point[x].newId, point[y].newId, z); 169 } 170 T queryPath(int x, int y){ 171 T ans = 0; 172 while(point[x].top != point[y].top){ 173 if(point[point[x].top].depth < point[point[y].top].depth) 174 swap(x, y); 175 ans += st.query(point[point[x].top].newId, point[x].newId); 176 x = point[point[x].top].father; 177 } 178 if(point[x].depth > point[y].depth) 179 swap(x, y); 180 ans += st.query(point[x].newId, point[y].newId); 181 return ans; 182 } 183 void updateSon(int x, T z){ 184 st.update(point[x].newId, point[x].newId + point[x].size - 1, z); 185 } 186 T querySon(int x){ 187 return st.query(point[x].newId, point[x].newId + point[x].size - 1); 188 } 189 T queryPoint(int x) { 190 return queryPath(x, x); 191 } 192 void updatePoint(int x, T z) { 193 updatePath(x, x, z); 194 } 195 }; 196 197 class Solution { 198 private: 199 int n, m, p; 200 TreeToLink<int> ttl; 201 public: 202 void solve() { 203 while(~scanf("%d%d%d", &n, &m, &p)){ 204 ttl.clear(n); 205 for(int i = 0, a, b; i < m; i ++) { 206 scanf("%d%d", &a, &b); 207 ttl.addEdgeTwoWay(a, b); 208 } 209 ttl.preWork(); 210 while(p --) { 211 char opt; 212 int a, b, c; 213 scanf(" %c%d", &opt, &a); 214 if(opt == I) { 215 scanf("%d%d", &b, &c); 216 ttl.updatePath(a, b, c); 217 } else if(opt == D) { 218 scanf("%d%d", &b, &c); 219 ttl.updatePath(a, b, -c); 220 } else if(opt == Q) { 221 printf("%d\n", ttl.queryPoint(a)); 222 } 223 } 224 } 225 } 226 } DarkScoCu; 227 228 int main() { 229 DarkScoCu.solve(); 230 return 0; 231 }

hdu 3966 Aragorn's Story : 樹鏈剖分 O(nlogn)建樹 O((logn)²)修改與查詢