Spoj--375(树链剖分,线段树)

2014-10-05 13:10:03

思路:树链剖分启蒙题。树链剖分就是把一棵树剖分成轻链和重链。一个节点的重儿子的含义:所有儿子中以其为根的子树最大的子节点。

主要维护的几个值:

son[p]:p的重儿子

top[p]:p所在链的顶节点

fa[p]:p的父亲节点

sz[p]:以p为根的子树的结点数

dep[p]:p的深度(root为0)

w[p]:p节点在线段树中的位置

aw[p]:w[]数组的反含义,即线段树中节点在输入顺序中的编号

  1 /*************************************************************************
  2     > File Name: sp375.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com 
  5     > Created Time: Sat 04 Oct 2014 08:42:34 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 = 10010;
 26 
 27 int T,N;
 28 int dep[maxn],sz[maxn],son[maxn],fa[maxn],top[maxn],tsz,w[maxn],tmax[maxn << 2];
 29 int first[maxn],next[maxn << 1],ver[maxn << 1],ecnt;
 30 int e[maxn][3];
 31 
 32 inline int read(){
 33     int x = 0,f = 1;char ch = getchar();
 34     while(ch < '0' || ch > '9'){if(ch == '-')f=-1;ch = getchar();}
 35     while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
 36     return x * f;
 37 }
 38 
 39 void Add_edge(int u,int v){
 40     next[++ecnt] = first[u];
 41     ver[ecnt] = v;
 42     first[u] = ecnt;
 43 }
 44 
 45 void Dfs(int p){
 46     sz[p] = 1;
 47     son[p] = -1;
 48     int maxx = 0;
 49     for(int i = first[p]; i != -1; i = next[i]) if(ver[i] != fa[p]){
 50         dep[ver[i]] = dep[p] + 1;
 51         fa[ver[i]] = p;
 52         Dfs(ver[i]);
 53         if(sz[ver[i]] > maxx){
 54             son[p] = ver[i];
 55             maxx = sz[ver[i]];
 56         }
 57         sz[p] += sz[ver[i]];
 58     }
 59 }
 60 
 61 void Build_tree(int p,int tp){
 62     w[p] = ++tsz;
 63     top[p] = tp;
 64     if(son[p] != -1) Build_tree(son[p],tp);
 65     for(int i = first[p]; i != -1; i = next[i])
 66         if(ver[i] != son[p] && ver[i] != fa[p])
 67             Build_tree(ver[i],ver[i]);
 68 }
 69 
 70 void Update_tree(int a,int v,int p,int l,int r){
 71     if(l == r){
 72         tmax[p] = v;
 73         return;
 74     }
 75     int mid = getmid(l,r);
 76     if(a <= mid) Update_tree(a,v,lp,l,mid);
 77     else Update_tree(a,v,rp,mid + 1,r);
 78     tmax[p] = max(tmax[lp],tmax[rp]);
 79 }
 80 
 81 int Query_tree(int a,int b,int p,int l,int r){
 82     if(a <= l && r <= b)
 83         return tmax[p];
 84     int res = -INF,mid = getmid(l,r);
 85     if(a <= mid) res = max(res,Query_tree(a,b,lp,l,mid));
 86     if(b > mid) res = max(res,Query_tree(a,b,rp,mid + 1,r));
 87     return res;
 88 }
 89 
 90 int Find(int a,int b){
 91     int f1 = top[a],f2 = top[b];
 92     int ans = 0;
 93     while(f1 != f2){
 94         if(dep[f1] > dep[f2]){
 95             swap(a,b);
 96             swap(f1,f2);
 97         }
 98         ans = max(ans,Query_tree(w[f2],w[b],1,1,tsz));
 99         b = fa[f2];
100         f2 = top[b];
101     }
102     if(a == b) return ans;
103     if(dep[a] > dep[b]) swap(a,b);
104     return max(ans,Query_tree(w[son[a]],w[b],1,1,tsz));
105 }
106 
107 void Init(){
108     tsz = -1;
109     fa[1] = dep[1] = 0;
110     memset(sz,0,sizeof(sz));
111     memset(tmax,0,sizeof(tmax));
112     memset(first,-1,sizeof(first));
113     ecnt = 0;
114 }
115 
116 int main(){
117     char s[10];
118     int a,b,c;
119     T = read();
120     while(T--){
121         N = read();
122         Init();
123         for(int i = 1; i < N; ++i){
124             a = read(),b = read(),c = read();
125             e[i][0] = a,e[i][1] = b,e[i][2] = c;
126             Add_edge(a,b);
127             Add_edge(b,a);
128         }
129         Dfs(1);
130         Build_tree(1,1);
131         for(int i = 1; i < N; ++i){
132             if(dep[e[i][0]] > dep[e[i][1]]) swap(e[i][0],e[i][1]);
133             Update_tree(w[e[i][1]],e[i][2],1,1,tsz);
134         }
135         while(scanf("%s",s) != EOF){
136             if(s[0] == 'D') break;
137             a = read(),b = read();
138             if(s[0] == 'C')
139                 Update_tree(w[e[a][1]],b,1,1,tsz);
140             else
141                 printf("%d\n",Find(a,b));
142         }
143     }
144     return 0;
145 }

 

posted @ 2014-10-05 16:30  Naturain  阅读(132)  评论(0)    收藏  举报