SPOJ 375 (树链剖分 - 边权剖分 - 修改单边权)

题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28982#problem/I

给你一棵有边权的树,有两个操作:一个操作是输出l到r点之间的最大的边权,另一个操作是修改某条边的权值。

这题是树链剖分的简单模版题,代码如下:

  1 //修改单边权
  2 #include <iostream>
  3 #include <cstdio>
  4 #include <cstring>
  5 using namespace std;
  6 const int MAXN = 1e4 + 10;
  7 struct data {
  8     int next , to , cost;
  9 }edge[MAXN << 1];
 10 int head[MAXN] , top[MAXN] , id[MAXN] , par[MAXN] , dep[MAXN] , size[MAXN] , son[MAXN];
 11 int cnt , tot , v[MAXN] , u[MAXN] , cost[MAXN];
 12 
 13 void init() {
 14     cnt = tot = 0;
 15     memset(head , -1 , sizeof(head));
 16 }
 17 
 18 inline void add(int u , int v , int cost) {
 19     edge[cnt].next = head[u];
 20     edge[cnt].to = v;
 21     edge[cnt].cost = cost;
 22     head[u] = cnt++;
 23 }
 24 
 25 void dfs_1(int u , int p , int d) {
 26     dep[u] = d , par[u] = p , size[u] = 1 , son[u] = u;
 27     for(int i = head[u] ; ~i ; i = edge[i].next) {
 28         int v = edge[i].to;
 29         if(v == p)
 30             continue;
 31         dfs_1(v , u , d + 1);
 32         if(size[son[u]] < size[v])
 33             son[u] = v;
 34         size[u] += size[v];
 35     }
 36 }
 37 
 38 void dfs_2(int u , int p , int t) {
 39     top[u] = t , id[u] = ++tot;
 40     if(son[u] != u)
 41         dfs_2(son[u] , u , t);
 42     for(int i = head[u] ; ~i ; i = edge[i].next) {
 43         int v = edge[i].to;
 44         if(v == p || v == son[u]) 
 45             continue;
 46         dfs_2(v , u , v);
 47     }
 48 }
 49 
 50 struct segtree {
 51     int l , r , Max;
 52 }T[MAXN << 2];
 53 
 54 void build(int p , int l , int r) {
 55     int mid = (l + r) >> 1;
 56     T[p].l = l , T[p].r = r;
 57     if(l == r)
 58         return ;
 59     build(p << 1 , l , mid);
 60     build((p << 1)|1 , mid + 1 , r);
 61 }
 62 
 63 void updata(int p , int pos , int num) {
 64     int mid = (T[p].l + T[p].r) >> 1;
 65     if(T[p].l == T[p].r) {
 66         T[p].Max = num;
 67         return ;
 68     }
 69     if(pos <= mid)
 70         updata(p << 1 , pos , num);
 71     else
 72         updata((p << 1)|1 , pos , num);
 73     T[p].Max = max(T[p << 1].Max , T[(p << 1)|1].Max);
 74 }
 75 
 76 int query(int p , int l , int r) {
 77     int mid = (T[p].l + T[p].r) >> 1;
 78     if(l == T[p].l && T[p].r == r)
 79         return T[p].Max;
 80     if(r <= mid)
 81         return query(p << 1 , l , r);
 82     else if(l > mid)
 83         return query((p << 1)|1 , l , r);
 84     else
 85         return max(query(p << 1 , l , mid) , query((p << 1)|1 , mid + 1 , r));
 86 }
 87 
 88 int Find(int l , int r) {
 89     int pl = top[l] , pr = top[r] , Max = 0;
 90     while(pl != pr) {
 91         if(dep[pl] > dep[pr]) {
 92             Max = max(Max , query(1 , id[pl] , id[l]));
 93             l = par[pl];
 94             pl = top[l];
 95         }
 96         else {
 97             Max = max(Max , query(1 , id[pr] , id[r]));
 98             r = par[pr];
 99             pr = top[r];
100         }
101     }
102     if(r == l)
103         return Max;
104     else if(dep[r] > dep[l])
105         return max(Max , query(1 , id[son[l]] , id[r]));
106     else 
107         return max(Max , query(1 , id[son[r]] , id[l]));
108 }
109 
110 int main()
111 {
112     int t , n , l , r;
113     scanf("%d" , &t);
114     while(t--) {
115         scanf("%d" , &n);
116         init();
117         for(int i = 1 ; i < n ; ++i) {
118             scanf("%d %d %d" , u + i , v + i , cost + i);
119             add(u[i] , v[i] , cost[i]);
120             add(v[i] , u[i] , cost[i]);
121         }
122         dfs_1(1 , 1 , 0);
123         dfs_2(1 , 1 , 1);
124         build(1 , 1 , tot);
125         for(int i = 1 ; i < n ; ++i) {
126             if(dep[u[i]] > dep[v[i]])
127                 swap(u[i] , v[i]);
128             updata(1 , id[v[i]] , cost[i]);
129         }
130         char q[10];
131         while(scanf("%s" , q) && q[0] != 'D') {
132             scanf("%d %d" , &l , &r);
133             if(q[0] == 'C') {
134                 updata(1 , id[v[l]] , r);        
135             }
136             else {
137                 printf("%d\n" , Find(l , r));
138             }
139         }
140     }
141     return 0;
142 }

 

posted @ 2016-05-21 20:45  Recoder  阅读(267)  评论(0编辑  收藏  举报