题目链接:
http://www.spoj.com/problems/QTREE/
375. Query on a treeProblem code: QTREE |
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1.
We will ask you to perfrom some instructions of the following form:
The first line of input contains an integer t, the number of test cases (t <= 20). t test cases follow.
For each test case:
There is one blank line between successive tests.
For each "QUERY" operation, write one integer representing its result.
Input: 1 3 1 2 1 2 3 2 QUERY 1 2 CHANGE 1 3 QUERY 1 2 DONE Output: 1 3
树链剖分入门题:
1 /* ********************************************** 2 Author : kuangbin 3 Created Time: 2013/8/11 22:00:02 4 File Name : F:\2013ACM练习\专题学习\数链剖分\SPOJ_QTREE.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 using namespace std; 19 20 const int MAXN = 10010; 21 struct Edge 22 { 23 int to,next; 24 }edge[MAXN*2]; 25 int head[MAXN],tot; 26 int top[MAXN];//top[v]表示v所在的重链的顶端节点 27 int fa[MAXN]; //父亲节点 28 int deep[MAXN];//深度 29 int num[MAXN];//num[v]表示以v为根的子树的节点数 30 int p[MAXN];//p[v]表示v与其父亲节点的连边在线段树中的位置 31 int fp[MAXN];//和p数组相反 32 int son[MAXN];//重儿子 33 int pos; 34 void init() 35 { 36 tot = 0; 37 memset(head,-1,sizeof(head)); 38 pos = 0; 39 memset(son,-1,sizeof(son)); 40 } 41 void addedge(int u,int v) 42 { 43 edge[tot].to = v;edge[tot].next = head[u];head[u] = tot++; 44 } 45 void dfs1(int u,int pre,int d) //第一遍dfs求出fa,deep,num,son 46 { 47 deep[u] = d; 48 fa[u] = pre; 49 num[u] = 1; 50 for(int i = head[u];i != -1; i = edge[i].next) 51 { 52 int v = edge[i].to; 53 if(v != pre) 54 { 55 dfs1(v,u,d+1); 56 num[u] += num[v]; 57 if(son[u] == -1 || num[v] > num[son[u]]) 58 son[u] = v; 59 } 60 } 61 } 62 void getpos(int u,int sp) //第二遍dfs求出top和p 63 { 64 top[u] = sp; 65 if(son[u] != -1) 66 { 67 p[u] = pos++; 68 fp[p[u]] = u; 69 getpos(son[u],sp); 70 } 71 else 72 { 73 p[u] = pos++; 74 fp[p[u]] = u; 75 return; 76 } 77 for(int i = head[u] ; i != -1; i = edge[i].next) 78 { 79 int v = edge[i].to; 80 if(v != son[u] && v != fa[u]) 81 getpos(v,v); 82 } 83 } 84 85 //线段树 86 struct Node 87 { 88 int l,r; 89 int Max; 90 }segTree[MAXN*3]; 91 void build(int i,int l,int r) 92 { 93 segTree[i].l = l; 94 segTree[i].r = r; 95 segTree[i].Max = 0; 96 if(l == r)return; 97 int mid = (l+r)/2; 98 build(i<<1,l,mid); 99 build((i<<1)|1,mid+1,r); 100 } 101 void push_up(int i) 102 { 103 segTree[i].Max = max(segTree[i<<1].Max,segTree[(i<<1)|1].Max); 104 } 105 void update(int i,int k,int val) // 更新线段树的第k个值为val 106 { 107 if(segTree[i].l == k && segTree[i].r == k) 108 { 109 segTree[i].Max = val; 110 return; 111 } 112 int mid = (segTree[i].l + segTree[i].r)/2; 113 if(k <= mid)update(i<<1,k,val); 114 else update((i<<1)|1,k,val); 115 push_up(i); 116 } 117 int query(int i,int l,int r) //查询线段树中[l,r] 的最大值 118 { 119 if(segTree[i].l == l && segTree[i].r == r) 120 return segTree[i].Max; 121 int mid = (segTree[i].l + segTree[i].r)/2; 122 if(r <= mid)return query(i<<1,l,r); 123 else if(l > mid)return query((i<<1)|1,l,r); 124 else return max(query(i<<1,l,mid),query((i<<1)|1,mid+1,r)); 125 } 126 int find(int u,int v)//查询u->v边的最大值 127 { 128 int f1 = top[u], f2 = top[v]; 129 int tmp = 0; 130 while(f1 != f2) 131 { 132 if(deep[f1] < deep[f2]) 133 { 134 swap(f1,f2); 135 swap(u,v); 136 } 137 tmp = max(tmp,query(1,p[f1],p[u])); 138 u = fa[f1]; f1 = top[u]; 139 } 140 if(u == v)return tmp; 141 if(deep[u] > deep[v]) swap(u,v); 142 return max(tmp,query(1,p[son[u]],p[v])); 143 } 144 int e[MAXN][3]; 145 int main() 146 { 147 //freopen("in.txt","r",stdin); 148 //freopen("out.txt","w",stdout); 149 int T; 150 int n; 151 scanf("%d",&T); 152 while(T--) 153 { 154 init(); 155 scanf("%d",&n); 156 for(int i = 0;i < n-1;i++) 157 { 158 scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]); 159 addedge(e[i][0],e[i][1]); 160 addedge(e[i][1],e[i][0]); 161 } 162 dfs1(1,0,0); 163 getpos(1,1); 164 build(1,0,pos-1); 165 for(int i = 0;i < n-1; i++) 166 { 167 if(deep[e[i][0]] > deep[e[i][1]]) 168 swap(e[i][0],e[i][1]); 169 update(1,p[e[i][1]],e[i][2]); 170 } 171 char op[10]; 172 int u,v; 173 while(scanf("%s",op) == 1) 174 { 175 if(op[0] == 'D')break; 176 scanf("%d%d",&u,&v); 177 if(op[0] == 'Q') 178 printf("%d\n",find(u,v)); 179 else update(1,p[e[u-1][1]],v); 180 } 181 } 182 return 0; 183 }