码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 3966 Aragorn's Story : 树链剖分 O(nlogn)建树 O((logn)²)修改与查询

时间:2019-04-12 23:14:49      阅读:130      评论:0      收藏:0      [点我收藏+]

标签:char   typename   style   hdu   vector   query   log   add   div   

  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)²)修改与查询

标签:char   typename   style   hdu   vector   query   log   add   div   

原文地址:https://www.cnblogs.com/DarkScoCu/p/10699145.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!