POJ 3237 Tree (树链剖分)
| Time Limit:?5000MS | ? | Memory Limit:?131072K |
| Total Submissions:?2825 | ? | Accepted:?769 |
Description
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
13 1 2 1 2 3 2 QUERY 1 2 CHANGE 1 3 QUERY 1 2 DONESample Output
1 3Source
POJ Monthly--2007.06.03, Lei, Tao?
樹鏈剖分+線段樹實(shí)現(xiàn)
?
?
1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013/8/17 4:04:42 4 File Name :F:\2013ACM練習(xí)\專題學(xué)習(xí)\數(shù)鏈剖分\POJ3237Tree.cpp 5 ************************************************ */ 6 7 #include <stdio.h> 8 #include <string.h> 9 #include <iostream> 10 #include <algorithm> 11 #include <vector> 12 #include <queue> 13 #include <set> 14 #include <map> 15 #include <string> 16 #include <math.h> 17 #include <stdlib.h> 18 #include <time.h> 19 using namespace std; 20 21 const int MAXN = 100010; 22 struct Edge 23 { 24 int to,next; 25 }edge[MAXN*2]; 26 int head[MAXN],tot; 27 int top[MAXN];//top[v]表示v所在的重鏈的頂端節(jié)點(diǎn) 28 int fa[MAXN]; //父親節(jié)點(diǎn) 29 int deep[MAXN];//深度 30 int num[MAXN];//num[v]表示以v為根的子樹的節(jié)點(diǎn)數(shù) 31 int p[MAXN];//p[v]表示v與其父親節(jié)點(diǎn)的連邊在線段樹中的位置 32 int fp[MAXN];//和p數(shù)組相反 33 int son[MAXN];//重兒子 34 int pos; 35 void init() 36 { 37 tot = 0; 38 memset(head,-1,sizeof(head)); 39 pos = 0; 40 memset(son,-1,sizeof(son)); 41 } 42 void addedge(int u,int v) 43 { 44 edge[tot].to = v;edge[tot].next = head[u];head[u] = tot++; 45 } 46 void dfs1(int u,int pre,int d) //第一遍dfs求出fa,deep,num,son 47 { 48 deep[u] = d; 49 fa[u] = pre; 50 num[u] = 1; 51 for(int i = head[u];i != -1; i = edge[i].next) 52 { 53 int v = edge[i].to; 54 if(v != pre) 55 { 56 dfs1(v,u,d+1); 57 num[u] += num[v]; 58 if(son[u] == -1 || num[v] > num[son[u]]) 59 son[u] = v; 60 } 61 } 62 } 63 void getpos(int u,int sp) //第二遍dfs求出top和p 64 { 65 top[u] = sp; 66 p[u] = pos++; 67 fp[p[u]] = u; 68 if(son[u] == -1) return; 69 getpos(son[u],sp); 70 for(int i = head[u] ; i != -1; i = edge[i].next) 71 { 72 int v = edge[i].to; 73 if(v != son[u] && v != fa[u]) 74 getpos(v,v); 75 } 76 } 77 78 //線段樹 79 struct Node 80 { 81 int l,r; 82 int Max; 83 int Min; 84 int ne; 85 }segTree[MAXN*3]; 86 void build(int i,int l,int r) 87 { 88 segTree[i].l = l; 89 segTree[i].r = r; 90 segTree[i].Max = 0; 91 segTree[i].Min = 0; 92 segTree[i].ne = 0; 93 if(l == r)return; 94 int mid = (l+r)/2; 95 build(i<<1,l,mid); 96 build((i<<1)|1,mid+1,r); 97 } 98 void push_up(int i) 99 { 100 segTree[i].Max = max(segTree[i<<1].Max,segTree[(i<<1)|1].Max); 101 segTree[i].Min = min(segTree[i<<1].Min,segTree[(i<<1)|1].Min); 102 } 103 void push_down(int i) 104 { 105 if(segTree[i].l == segTree[i].r)return; 106 if(segTree[i].ne) 107 { 108 segTree[i<<1].Max = -segTree[i<<1].Max; 109 segTree[i<<1].Min = -segTree[i<<1].Min; 110 swap(segTree[i<<1].Min,segTree[i<<1].Max); 111 segTree[(i<<1)|1].Max = -segTree[(i<<1)|1].Max; 112 segTree[(i<<1)|1].Min = -segTree[(i<<1)|1].Min; 113 swap(segTree[(i<<1)|1].Max,segTree[(i<<1)|1].Min); 114 segTree[i<<1].ne ^= 1; 115 segTree[(i<<1)|1].ne ^= 1; 116 segTree[i].ne = 0; 117 } 118 } 119 void update(int i,int k,int val) // 更新線段樹的第k個(gè)值為val 120 { 121 if(segTree[i].l == k && segTree[i].r == k) 122 { 123 segTree[i].Max = val; 124 segTree[i].Min = val; 125 segTree[i].ne = 0; 126 return; 127 } 128 push_down(i); 129 int mid = (segTree[i].l + segTree[i].r)/2; 130 if(k <= mid)update(i<<1,k,val); 131 else update((i<<1)|1,k,val); 132 push_up(i); 133 } 134 void ne_update(int i,int l,int r) // 更新線段樹的區(qū)間[l,r]取反 135 { 136 if(segTree[i].l == l && segTree[i].r == r) 137 { 138 segTree[i].Max = -segTree[i].Max; 139 segTree[i].Min = -segTree[i].Min; 140 swap(segTree[i].Max,segTree[i].Min); 141 segTree[i].ne ^= 1; 142 return; 143 } 144 push_down(i); 145 int mid = (segTree[i].l + segTree[i].r)/2; 146 if(r <= mid)ne_update(i<<1,l,r); 147 else if(l > mid) ne_update((i<<1)|1,l,r); 148 else 149 { 150 ne_update(i<<1,l,mid); 151 ne_update((i<<1)|1,mid+1,r); 152 } 153 push_up(i); 154 } 155 int query(int i,int l,int r) //查詢線段樹中[l,r] 的最大值 156 { 157 if(segTree[i].l == l && segTree[i].r == r) 158 return segTree[i].Max; 159 push_down(i); 160 int mid = (segTree[i].l + segTree[i].r)/2; 161 if(r <= mid)return query(i<<1,l,r); 162 else if(l > mid)return query((i<<1)|1,l,r); 163 else return max(query(i<<1,l,mid),query((i<<1)|1,mid+1,r)); 164 push_up(i); 165 } 166 int findmax(int u,int v)//查詢u->v邊的最大值 167 { 168 int f1 = top[u], f2 = top[v]; 169 int tmp = -100000000; 170 while(f1 != f2) 171 { 172 if(deep[f1] < deep[f2]) 173 { 174 swap(f1,f2); 175 swap(u,v); 176 } 177 tmp = max(tmp,query(1,p[f1],p[u])); 178 u = fa[f1]; f1 = top[u]; 179 } 180 if(u == v)return tmp; 181 if(deep[u] > deep[v]) swap(u,v); 182 return max(tmp,query(1,p[son[u]],p[v])); 183 } 184 void Negate(int u,int v)//把u-v路徑上的邊的值都設(shè)置為val 185 { 186 int f1 = top[u], f2 = top[v]; 187 while(f1 != f2) 188 { 189 if(deep[f1] < deep[f2]) 190 { 191 swap(f1,f2); 192 swap(u,v); 193 } 194 ne_update(1,p[f1],p[u]); 195 u = fa[f1]; f1 = top[u]; 196 } 197 if(u == v)return; 198 if(deep[u] > deep[v]) swap(u,v); 199 return ne_update(1,p[son[u]],p[v]); 200 } 201 int e[MAXN][3]; 202 int main() 203 { 204 //freopen("in.txt","r",stdin); 205 //freopen("out.txt","w",stdout); 206 int T; 207 int n; 208 scanf("%d",&T); 209 while(T--) 210 { 211 init(); 212 scanf("%d",&n); 213 for(int i = 0;i < n-1;i++) 214 { 215 scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]); 216 addedge(e[i][0],e[i][1]); 217 addedge(e[i][1],e[i][0]); 218 } 219 dfs1(1,0,0); 220 getpos(1,1); 221 build(1,0,pos-1); 222 for(int i = 0;i < n-1; i++) 223 { 224 if(deep[e[i][0]] > deep[e[i][1]]) 225 swap(e[i][0],e[i][1]); 226 update(1,p[e[i][1]],e[i][2]); 227 } 228 char op[10]; 229 int u,v; 230 while(scanf("%s",op) == 1) 231 { 232 if(op[0] == 'D')break; 233 scanf("%d%d",&u,&v); 234 if(op[0] == 'Q') 235 printf("%d\n",findmax(u,v));//查詢u->v路徑上邊權(quán)的最大值 236 else if(op[0] == 'C') 237 update(1,p[e[u-1][1]],v);//改變第u條邊的值為v 238 else Negate(u,v); 239 } 240 } 241 return 0; 242 }?
?
?
總結(jié)
以上是生活随笔為你收集整理的POJ 3237 Tree (树链剖分)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 学IT技术几个好的网站
- 下一篇: c语言过程中的理论杂篇。