2014-10-06 22:08:46
思路:一道裸的树剖,线段树维护的是边,所以姿势稍有不同。建树的过程不用另开Build函数,而使用Update将边一条一条更新进树中。
要注意!线段树中第 i 个叶子节点存的是第 i - 1条边。(这样就使得第一条边为根节点与其父节点的边,是虚的边)
1 /************************************************************************* 2 > File Name: 2763.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Sun 05 Oct 2014 06:39:02 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <queue> 16 #include <iostream> 17 #include <algorithm> 18 using namespace std; 19 #define lp (p << 1) 20 #define rp (p << 1|1) 21 #define getmid(l,r) (l + (r - l) / 2) 22 #define MP(a,b) make_pair(a,b) 23 typedef long long ll; 24 const int INF = 1 << 30; 25 const int maxn = 100010; 26 27 int n,q,s; 28 int first[maxn],next[maxn << 1],ver[maxn << 1],ecnt; 29 int dep[maxn],sz[maxn],son[maxn],fa[maxn],top[maxn],w[maxn],aw[maxn],tsz; 30 int e[maxn][3],sum[maxn << 2]; 31 32 void Init(){ 33 memset(first,-1,sizeof(first)); 34 ecnt = 0; 35 tsz = -1; 36 } 37 38 void Add_edge(int u,int v){ 39 next[++ecnt] = first[u]; 40 ver[ecnt] = v; 41 first[u] = ecnt; 42 } 43 44 void Dfs(int p,int pre,int d){ 45 sz[p] = 1; 46 dep[p] = d; 47 son[p] = -1; 48 fa[p] = pre; 49 int tmp = 0,v; 50 for(int i = first[p]; i != -1; i = next[i]) if((v = ver[i]) != pre){ 51 Dfs(v,p,d + 1); 52 if(sz[v] > tmp){ 53 tmp = sz[v]; 54 son[p] = v; 55 } 56 sz[p] += sz[v]; 57 } 58 } 59 60 void Dfs_pos(int p,int tp){ 61 w[p] = ++tsz; 62 aw[tsz] = p; 63 top[p] = tp; 64 if(son[p] != -1) Dfs_pos(son[p],tp); 65 for(int i = first[p]; i != -1; i = next[i]){ 66 int v = ver[i]; 67 if(v != son[p] && v != fa[p]) 68 Dfs_pos(v,v); 69 } 70 } 71 72 int Query_sum(int a,int b,int p,int l,int r){ 73 if(a <= l && r <= b) 74 return sum[p]; 75 int mid = getmid(l,r),res = 0; 76 if(a <= mid) res += Query_sum(a,b,lp,l,mid); 77 if(b > mid) res += Query_sum(a,b,rp,mid + 1,r); 78 return res; 79 } 80 81 int Find(int a,int b){ 82 int f1 = top[a],f2 = top[b]; 83 int res = 0; 84 while(f1 != f2){ 85 if(dep[f1] > dep[f2]){ 86 swap(a,b); 87 swap(f1,f2); 88 } 89 res += Query_sum(w[f2],w[b],1,1,tsz); 90 b = fa[f2]; 91 f2 = top[b]; 92 } 93 if(a == b) return res; 94 if(dep[a] > dep[b]) swap(a,b); 95 res += Query_sum(w[son[a]],w[b],1,1,tsz); 96 return res; 97 } 98 99 void Update_tree(int a,int c,int p,int l,int r){ 100 if(l == r){ 101 sum[p] = c; 102 return; 103 } 104 int mid = getmid(l,r); 105 if(a <= mid) Update_tree(a,c,lp,l,mid); 106 else Update_tree(a,c,rp,mid + 1,r); 107 sum[p] = sum[lp] + sum[rp]; 108 } 109 110 int main(){ 111 int a,b,c,f; 112 Init(); 113 scanf("%d%d%d",&n,&q,&s); 114 for(int i = 1; i < n; ++i){ 115 scanf("%d%d%d",&a,&b,&c); 116 Add_edge(a,b); 117 Add_edge(b,a); 118 e[i][0] = a,e[i][1] = b,e[i][2] = c; 119 } 120 Dfs(1,0,0); 121 Dfs_pos(1,1); 122 for(int i = 1; i < n; ++i){ 123 if(dep[e[i][0]] > dep[e[i][1]]) swap(e[i][0],e[i][1]); 124 Update_tree(w[e[i][1]],e[i][2],1,1,tsz); 125 } 126 for(int i = 1; i <= q; ++i){ 127 scanf("%d",&f); 128 if(f == 0){ 129 scanf("%d",&a); 130 printf("%d\n",Find(a,s)); 131 s = a; 132 } 133 else{ 134 scanf("%d%d",&a,&c); 135 Update_tree(w[e[a][1]],c,1,1,tsz); 136 } 137 } 138 return 0; 139 }