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\n", ttl.queryPath(now, b));
234                 now = b;
235             }
236         }
237     }
238 } DarkScoCu;
239
240 int main() {
241     DarkScoCu.solve();
242     return 0;
243 }

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

时间: 2024-11-13 09:00:53

poj 2763 Housewife Wind : 树链剖分维护边 O(nlogn)建树 O((logn)²)修改与查询的相关文章

POJ 2763 Housewife Wind (树链剖分+线段树)

题目链接:POJ 2763 Housewife Wind 题意:抽象出来就是 一棵已知节点之间的边权,两个操作,1·修改边权,2·询问两个节点之间的边权和. AC代码: #include <string.h> #include <stdio.h> #include <algorithm> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int

POJ 2763 Housewife Wind (树链剖分)

题目地址:POJ 2763 还是树链剖分模板题...不多说.. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include <stdio.h>

POJ 2763 Housewife Wind 树链拋分

一.前言 这破题WA了一天,最后重构还是WA,最后通过POJ讨论版得到的数据显示,我看上去是把某个变量写错了..于是,还是低级错误背锅啊....代码能力有待进一步提升2333333 二.题意 某家庭主妇住在一棵树上,他的若干个孩子在树的若干个节点上有分布,主妇同学需要从某给定节点出发,飞到树上的制定节点,在过程中,边权可能会发生改变,问从当前节点到指定节点的边权和. 三.解法 树链拋分,点更新查区间. // #include<bits/stdc++.h> #include<iostrea

hdu 3966 Aragorn&#39;s Story : 树链剖分 O(nlogn)建树 O((logn)&#178;)修改与查询

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 <ty

POJ 2763 Housewife Wind LCA转RMQ+时间戳+线段树成段更新

题目来源:POJ 2763 Housewife Wind 题意:给你一棵树 2种操作0 x 求当前点到x的最短路 然后当前的位置为x; 1 i x 将第i条边的权值置为x 思路:树上两点u, v距离为d[u]+d[v]-2*d[LCA(u,v)] 现在d数组是变化的 对应每一条边的变化 他修改的是一个区间 用时间戳处理每个点管辖的区域 然后用线段树修改 线段树的叶子节点村的是根到每一个点的距离 求最近公共祖先没差别 只是堕落用线段树维护d数组 各种错误 4个小时 伤不起 #include <cs

poj 2763 Housewife Wind(树链剖分+单点查询+区间修改)

题目链接:http://poj.org/problem?id=2763 题意:给一个数,边之间有权值,然后两种操作,第一种:求任意两点的权值和,第二,修改树上两点的权值. 题解:简单的树链剖分. #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int M = 1e5 + 10; struct Edge { int v , next; }edge[M &

POJ 2763 Housewife Wind(树链剖分+树状数组)

[题目链接] http://poj.org/problem?id=2763 [题目大意] 在一棵树上,给出一些边的边长,有修改边的边长的操作, 询问每次从当前点到目标点的最短距离 [题解] 树链剖分之后,相当于树状数组的单点更新和区间查询, 注意边权转点权之后链操作不覆盖deep最浅的点,这里容易出错 [代码] #include <cstdio> #include <cstring> #include <algorithm> using namespace std; c

POJ 2763 Housewife Wind (树链剖分)

题目链接~~> 做题感悟:这题说多了都是泪啊 !明明是一个简单的不能再简单的树链剖分,结果因为一个符号错误找了一下午. 解题思路:   树链剖分 + 线段树插点问线. 代码: #include<iostream> #include<sstream> #include<map> #include<cmath> #include<fstream> #include<queue> #include<vector> #inc

POJ 2763 Housewife Wind(树链剖分+线段树)

题意:在一颗树上,你在s位置,询问s到x的距离,然后移动到x点,第二种操作是修改一条边的权值 思路:直接树链剖分,不知道哪里出的bug,最后发现在主函数询问的时候好像有个标号改着改着改错了 代码: #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn=500008; int n,m,s; int a[maxn],sz[maxn],dep[m