POJ 3237 Tree

Tree

Time Limit: 5000ms
Memory Limit: 131072KB
This problem will be judged on PKU. Original ID: 3237
64-bit integer IO format: %lld      Java class name: Main
 
You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:
  1. CHANGE i v: Change the weight of the ith edge to v
  2. NEGATE a b: Negate the weight of every edge on the path from a to b
  3. QUERY a b: Find the maximum weight of edges on the path from a to b

Input

The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.

Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N − 1 lines each contains three integers ab and c, describing an edge connecting nodes a and b with weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “DONE” ends the test case.

Output

For each “QUERY” instruction, output the result on a separate line.

Sample Input

1

3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE

Sample Output

1
3

Source

 
解题:树链剖分
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 const int INF = 0x3f3f3f3f;
  7 const int maxn = 10010;
  8 struct arc{
  9     int to,w,next;
 10     arc(int x = 0,int y = 0,int z = -1){
 11         to = x;
 12         w = y;
 13         next = z;
 14     }
 15 }e[maxn<<1];
 16 struct node{
 17     int lt,rt,maxval,lazy,minval;
 18 }tree[maxn<<2];
 19 int head[maxn],fa[maxn],top[maxn],dep[maxn];
 20 int siz[maxn],son[maxn],loc[maxn];
 21 int clk,tot,n;
 22 void add(int u,int v,int w){
 23     e[tot] = arc(v,w,head[u]);
 24     head[u] = tot++;
 25 }
 26 void FindHeavyEdge(int u,int father,int depth){
 27     fa[u] = father;
 28     dep[u] = depth;
 29     son[u] = -1;
 30     siz[u] = 1;
 31     for(int i = head[u]; ~i; i = e[i].next){
 32         if(e[i].to == father) continue;
 33         FindHeavyEdge(e[i].to,u,depth + 1);
 34         siz[u] += siz[e[i].to];
 35         if(son[u] == -1 || siz[e[i].to] > siz[son[u]])
 36             son[u] = e[i].to;
 37     }
 38 }
 39 void ConnectHeavyEdge(int u,int ancestor){
 40     top[u] = ancestor;
 41     loc[u] = clk++;
 42     if(son[u] != -1) ConnectHeavyEdge(son[u],ancestor);
 43     for(int i = head[u]; ~i; i = e[i].next){
 44         if(e[i].to == fa[u] || e[i].to == son[u]) continue;
 45         ConnectHeavyEdge(e[i].to,e[i].to);
 46     }
 47 }
 48 void build(int lt,int rt,int v){
 49     tree[v].lt = lt;
 50     tree[v].rt = rt;
 51     tree[v].lazy = 1;
 52     tree[v].maxval = tree[v].minval = 0;
 53     if(lt == rt) return;
 54     int mid = (lt + rt)>>1;
 55     build(lt,mid,v<<1);
 56     build(mid + 1,rt,v<<1|1);
 57 }
 58 inline void pushdown(int v){
 59     if(tree[v].lazy == -1){
 60         tree[v<<1].lazy *= -1;
 61         tree[v<<1|1].lazy *= -1;
 62         swap(tree[v<<1].minval,tree[v<<1].maxval);
 63         tree[v<<1].maxval = -tree[v<<1].maxval;
 64         tree[v<<1].minval = -tree[v<<1].minval;
 65         swap(tree[v<<1|1].maxval,tree[v<<1|1].minval);
 66         tree[v<<1|1].maxval = -tree[v<<1|1].maxval;
 67         tree[v<<1|1].minval = -tree[v<<1|1].minval;
 68         tree[v].lazy = 1;
 69     }
 70 }
 71 inline void pushup(int v){
 72     tree[v].maxval = max(tree[v<<1].maxval,tree[v<<1|1].maxval);
 73     tree[v].minval = min(tree[v<<1].minval,tree[v<<1|1].minval);
 74 }
 75 void change(int pos,int val,int v){
 76     if(tree[v].lt == tree[v].rt){
 77         tree[v].maxval = tree[v].minval = val;
 78         return;
 79     }
 80     pushdown(v);
 81     if(pos <= tree[v<<1].rt) change(pos,val,v<<1);
 82     if(pos >= tree[v<<1|1].lt) change(pos,val,v<<1|1);
 83     pushup(v);
 84 }
 85 int Negate(int lt,int rt,int v){
 86     if(lt <= tree[v].lt && rt >= tree[v].rt){
 87         tree[v].lazy *= -1;
 88         swap(tree[v].maxval,tree[v].minval);
 89         tree[v].maxval = -tree[v].maxval;
 90         tree[v].minval = -tree[v].minval;
 91         return 0;
 92     }
 93     pushdown(v);
 94     if(lt <= tree[v<<1].rt) Negate(lt,rt,v<<1);
 95     if(rt >= tree[v<<1|1].lt) Negate(lt,rt,v<<1|1);
 96     pushup(v);
 97     return 0;
 98 }
 99 int query(int lt,int rt,int v){
100     if(lt <= tree[v].lt && rt >= tree[v].rt) return tree[v].maxval;
101     pushdown(v);
102     int ret = -INF;
103     if(lt <= tree[v<<1].rt) ret = query(lt,rt,v<<1);
104     if(rt >= tree[v<<1|1].lt) ret = max(ret,query(lt,rt,v<<1|1));
105     return ret;
106 }
107 int CAO(int u,int v,int (*f)(int,int,int)){
108     int ret = -INF;
109     while(top[u] != top[v]){
110         if(dep[top[u]] < dep[top[v]]) swap(u,v);
111         ret = max(ret,f(loc[top[u]],loc[u],1));
112         u = fa[top[u]];
113     }
114     if(u == v) return ret;
115     if(dep[u] > dep[v]) swap(u,v);
116     ret = max(ret,f(loc[son[u]],loc[v],1));
117     return ret;
118 }
119 int main(){
120     int kase,u,v,w;
121     scanf("%d",&kase);
122     while(kase--){
123         scanf("%d",&n);
124         tot = clk = 0;
125         memset(head,-1,sizeof head);
126         for(int i = 1; i < n; ++i){
127             scanf("%d%d%d",&u,&v,&w);
128             add(u,v,w);
129             add(v,u,w);
130         }
131         FindHeavyEdge(1,0,0);
132         ConnectHeavyEdge(1,1);
133         build(0,clk-1,1);
134         for(int i = 0; i < tot; i += 2){
135             u = e[i].to;
136             v = e[i + 1].to;
137             if(dep[u] < dep[v]) swap(u,v);
138             change(loc[u],e[i].w,1);
139         }
140         char op[10];
141         while(~scanf("%s",op)){
142             if(op[0] == 'D') break;
143             if(op[0] == 'Q'){
144                 scanf("%d%d",&u,&v);
145                 printf("%d\n",CAO(u,v,query));
146             }else if(op[0] == 'C'){
147                 scanf("%d%d",&u,&w);
148                 int ith = (u - 1)*2;
149                 if(dep[e[ith].to] < dep[e[ith+1].to]) ith++;
150                 change(loc[e[ith].to],w,1);
151             }else if(op[0] == 'N'){
152                 scanf("%d%d",&u,&v);
153                 CAO(u,v,Negate);
154             }
155         }
156     }
157     return 0;
158 }
View Code

 

posted @ 2015-09-28 19:46  狂徒归来  阅读(227)  评论(0编辑  收藏  举报