poj 2763 Housewife Wind : 树链剖分维护边 O(nlogn)建树 O((logn)²)修改与查询
Posted darkscocu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj 2763 Housewife Wind : 树链剖分维护边 O(nlogn)建树 O((logn)²)修改与查询相关的知识,希望对你有一定的参考价值。
1 /** 2 problem: http://poj.org/problem?id=2763 3 **/ 4 #include<stdio.h> 5 #include<stdlib.h> 6 #include<string.h> 7 #include<vector> 8 using namespace std; 9 10 const int MAXN = 100005; 11 12 template <typename T> 13 class SegmentTree { 14 private: 15 struct Node { 16 int left, right; 17 T sum, lazy; 18 } node[MAXN << 2]; 19 T data[MAXN]; 20 void pushUp(int root) { 21 node[root].sum = node[root << 1].sum + node[root << 1 | 1].sum; 22 } 23 void pushDown(int root) { 24 if(node[root].left == node[root].right) return; 25 int lson = root << 1; 26 int rson = root << 1 | 1; 27 node[lson].sum = node[root].lazy * (node[lson].right - node[lson].left + 1); 28 node[rson].sum = node[root].lazy * (node[rson].right - node[rson].left + 1); 29 node[lson].lazy = node[root].lazy; 30 node[rson].lazy = node[root].lazy; 31 node[root].lazy = 0; 32 } 33 public: 34 void build(int left, int right, int root = 1) { 35 node[root].left = left; 36 node[root].right = right; 37 node[root].lazy = 0; 38 if(left == right) { 39 node[root].sum = data[left]; 40 } else { 41 int mid = (left + right) >> 1; 42 build(left, mid, root << 1); 43 build(mid + 1, right, root << 1 | 1); 44 pushUp(root); 45 } 46 } 47 void update(int left, int right, T value, int root = 1) { 48 int lson = root << 1; 49 int rson = root << 1 | 1; 50 if(node[root].lazy) pushDown(root); 51 if(node[root].left == left && node[root].right == right) { 52 node[root].sum = value * (right - left + 1); 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 pushUp(root); 65 } 66 T query(int left, int right, int root = 1) { 67 int lson = root << 1; 68 int rson = root << 1 | 1; 69 if(node[root].lazy) pushDown(root); 70 if(node[root].left == left && node[root].right == right) { 71 return node[root].sum; 72 } 73 if(left >= node[rson].left) { 74 return query(left, right, rson); 75 } else if(right <= node[lson].right) { 76 return query(left, right, lson); 77 } else { 78 return query(left, node[lson].right, lson) + query(node[rson].left, right, rson); 79 } 80 } 81 void clear(int n, const vector<int> &d) { 82 for(int i = 1; i <= n; i ++) { 83 this->data[i] = d[i]; 84 } 85 build(1, n); 86 } 87 }; 88 89 template <typename T> 90 class TreeToLink { 91 private: 92 struct Point { 93 int size, son, depth, father, top, newId; 94 T data; 95 } point[MAXN]; 96 struct Edge { 97 int to, next; 98 } edge[MAXN << 1]; 99 int oldId[MAXN], first[MAXN], sign, sumOfPoint, cnt; 100 SegmentTree<T> st; 101 void dfs1(int u, int father = 0, int depth = 1) { 102 point[u].depth = depth; 103 point[u].father = father; 104 point[u].size = 1; 105 int maxson = -1; 106 for(int i = first[u]; i != -1; i = edge[i].next) { 107 int to = edge[i].to; 108 if(to == father) continue; 109 dfs1(to, u, depth + 1); 110 point[u].size += point[to].size; 111 if(point[to].size > maxson) { 112 point[u].son = to; 113 maxson = point[to].size; 114 } 115 } 116 } 117 void dfs2(int u, int top) { 118 point[u].newId = ++cnt; 119 oldId[cnt] = u; 120 point[u].top = top; 121 if(point[u].son == -1) { 122 return ; 123 } 124 dfs2(point[u].son, top); 125 for(int i = first[u]; i != -1; i = edge[i].next) { 126 int to = edge[i].to; 127 if(to == point[u].son || to == point[u].father) continue; 128 dfs2(to, to); 129 } 130 } 131 public: 132 void clear(int n) { 133 sumOfPoint = n; 134 sign = 0; 135 cnt = 0; 136 for(int i = 1; i <= n; i ++) { 137 first[i] = -1; 138 point[i].son = -1; 139 // scanf("%d", &point[i].data); // input 140 point[i].data = 0; 141 } 142 } 143 void addEdgeOneWay(int u, int v) { 144 edge[sign].to = v; 145 edge[sign].next = first[u]; 146 first[u] = sign ++; 147 } 148 void addEdgeTwoWay(int u, int v) { 149 addEdgeOneWay(u, v); 150 addEdgeOneWay(v, u); 151 } 152 void preWork(int x = 1) { 153 dfs1(x); 154 dfs2(x, x); 155 vector<int> data(sumOfPoint + 1); 156 for(int i = 1; i <= sumOfPoint; i ++) { 157 data[i] = point[oldId[i]].data; 158 } 159 st.clear(sumOfPoint, data); 160 } 161 void updatePath(int x, int y, T z){ 162 while(point[x].top != point[y].top){ 163 if(point[point[x].top].depth < point[point[y].top].depth) 164 swap(x, y); 165 st.update(point[point[x].top].newId, point[x].newId, z); 166 x = point[point[x].top].father; 167 } 168 if(point[x].depth > point[y].depth) 169 swap(x, y); 170 st.update(point[x].newId, point[y].newId, z); 171 } 172 T queryPath(int x, int y){ 173 T ans = 0; 174 while(point[x].top != point[y].top){ 175 if(point[point[x].top].depth < point[point[y].top].depth) 176 swap(x, y); 177 ans += st.query(point[point[x].top].newId, point[x].newId); 178 x = point[point[x].top].father; 179 } 180 if(x == y) return ans; // Edge 181 if(point[x].depth > point[y].depth) 182 swap(x, y); 183 // ans += st.query(point[x].newId, point[y].newId); // Point 184 ans += st.query(point[point[x].son].newId, point[y].newId); // Edge 185 return ans; 186 } 187 void updateSon(int x, T z){ 188 st.update(point[x].newId, point[x].newId + point[x].size - 1, z); 189 } 190 T querySon(int x){ 191 return st.query(point[x].newId, point[x].newId + point[x].size - 1); 192 } 193 T queryPoint(int x) { 194 return queryPath(x, x); 195 } 196 void updatePoint(int x, T z) { 197 updatePath(x, x, z); 198 } 199 bool deeper(int u, int v){ 200 return point[u].depth > point[v].depth; 201 } 202 }; 203 204 class Solution { 205 private: 206 int n, q, s; 207 TreeToLink<int> ttl; 208 struct Edge{ 209 int u, v, w; 210 }edge[MAXN]; 211 public: 212 void solve() { 213 scanf("%d%d%d", &n, &q, &s); 214 ttl.clear(n); 215 for(int i = 1; i < n; i ++){ 216 scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w); 217 ttl.addEdgeTwoWay(edge[i].u, edge[i].v); 218 } 219 ttl.preWork(s); 220 for(int i = 1; i < n; i ++){ 221 if(ttl.deeper(edge[i].u, edge[i].v)){ 222 swap(edge[i].u, edge[i].v); 223 } 224 ttl.updatePoint(edge[i].v, edge[i].w); 225 } 226 int now = s; 227 for(int i = 0, a, b, c; i < q; i ++){ 228 scanf("%d%d", &a, &b); 229 if(a == 1){ 230 scanf("%d", &c); 231 ttl.updatePoint(edge[b].v, c); 232 }else{ 233 printf("%d ", ttl.queryPath(now, b)); 234 now = b; 235 } 236 } 237 } 238 } DarkScoCu; 239 240 int main() { 241 DarkScoCu.solve(); 242 return 0; 243 }
以上是关于poj 2763 Housewife Wind : 树链剖分维护边 O(nlogn)建树 O((logn)²)修改与查询的主要内容,如果未能解决你的问题,请参考以下文章
POJ 2763 Housewife Wind(树链剖分)(线段树单点修改)
POJ 2763 Housewife Wind(DFS序+LCA+树状数组)
poj 2763 Housewife Wind(树链剖分+单点查询+区间修改)