POJ 3237 Tree
Tree
Time Limit: 5000ms
Memory Limit: 131072KB
This problem will be judged on PKU. Original ID: 323764-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:
- CHANGE i v: Change the weight of the ith edge to v
- NEGATE a b: Negate the weight of every edge on the path from a to b
- 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 a, b 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 }
夜空中最亮的星,照亮我前行