BZOJ 1036: [ZJOI2008]树的统计Count
1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 8812 Solved: 3588
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
Input
输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
Sample Input
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
Sample Output
4
1
2
2
10
6
5
6
5
16
解题:树链剖分
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 30010; 4 struct arc { 5 int to,next; 6 arc(int x = 0,int y = -1) { 7 to = x; 8 next = y; 9 } 10 } e[maxn<<1]; 11 struct node { 12 int lt,rt,sum,maxval; 13 } tree[maxn<<2]; 14 int head[maxn],fa[maxn],top[maxn],dep[maxn]; 15 int siz[maxn],son[maxn],loc[maxn],clk,tot; 16 void add(int u,int v) { 17 e[tot] = arc(v,head[u]); 18 head[u] = tot++; 19 } 20 void FindHeavyEdge(int u,int father,int depth) { 21 fa[u] = father; 22 dep[u] = depth; 23 son[u] = -1; 24 siz[u] = 1; 25 for(int i = head[u]; ~i; i = e[i].next) { 26 if(e[i].to == father) continue; 27 FindHeavyEdge(e[i].to,u,depth + 1); 28 siz[u] += siz[e[i].to]; 29 if(son[u] == -1 || siz[e[i].to] > siz[son[u]]) 30 son[u] = e[i].to; 31 } 32 } 33 void ConnectHeavyEdge(int u,int ancestor) { 34 loc[u] = clk++; 35 top[u] = ancestor; 36 if(son[u] != -1) ConnectHeavyEdge(son[u],ancestor); 37 for(int i = head[u]; ~i; i = e[i].next) { 38 if(e[i].to == fa[u] || son[u] == e[i].to) continue; 39 ConnectHeavyEdge(e[i].to,e[i].to); 40 } 41 } 42 void build(int lt,int rt,int v) { 43 tree[v].lt = lt; 44 tree[v].rt = rt; 45 tree[v].sum = 0; 46 tree[v].maxval = 0; 47 if(lt == rt) return; 48 int mid = (lt + rt)>>1; 49 build(lt,mid,v<<1); 50 build(mid + 1,rt,v<<1|1); 51 } 52 void update(int pos,int val,int v) { 53 if(tree[v].lt == tree[v].rt) { 54 tree[v].maxval = tree[v].sum = val; 55 return; 56 } 57 if(pos <= tree[v<<1].rt) update(pos,val,v<<1); 58 if(pos >= tree[v<<1|1].lt) update(pos,val,v<<1|1); 59 tree[v].sum = tree[v<<1].sum + tree[v<<1|1].sum; 60 tree[v].maxval = max(tree[v<<1].maxval,tree[v<<1|1].maxval); 61 } 62 int querySum(int lt,int rt,int v) { 63 if(lt <= tree[v].lt && rt >= tree[v].rt) return tree[v].sum; 64 int ret = 0; 65 if(lt <= tree[v<<1].rt) ret = querySum(lt,rt,v<<1); 66 if(rt >= tree[v<<1|1].lt) ret += querySum(lt,rt,v<<1|1); 67 return ret; 68 } 69 int queryMax(int lt,int rt,int v) { 70 if(lt <= tree[v].lt && rt >= tree[v].rt) return tree[v].maxval; 71 int ret = -0x3f3f3f3f; 72 if(lt <= tree[v<<1].rt) ret = queryMax(lt,rt,v<<1); 73 if(rt >= tree[v<<1|1].lt) ret = max(ret,queryMax(lt,rt,v<<1|1)); 74 return ret; 75 } 76 int sum(int a,int b) { 77 return a + b; 78 } 79 int mymax(int a,int b) { 80 return max(a,b); 81 } 82 int CAO(int u,int v,int (*f)(int,int,int),int (*g)(int,int),int ret = 0) { 83 while(top[u] != top[v]) { 84 if(dep[top[u]] < dep[top[v]]) swap(u,v); 85 ret = g(ret,f(loc[top[u]],loc[u],1)); 86 u = fa[top[u]]; 87 } 88 if(dep[u] > dep[v]) swap(u,v); 89 ret = g(ret,f(loc[u],loc[v],1)); 90 return ret; 91 } 92 int main() { 93 int n,m,u,v; 94 while(~scanf("%d",&n)) { 95 memset(head,-1,sizeof head); 96 tot = clk = 0; 97 for(int i = 1; i < n; ++i) { 98 scanf("%d%d",&u,&v); 99 add(u,v); 100 add(v,u); 101 } 102 FindHeavyEdge(1,0,0); 103 ConnectHeavyEdge(1,1); 104 build(0,clk-1,1); 105 for(int i = 1; i <= n; ++i){ 106 scanf("%d",&u); 107 update(loc[i],u,1); 108 } 109 scanf("%d",&m); 110 char op[20]; 111 while(m--){ 112 scanf("%s",op); 113 if(op[1] == 'S'){ 114 scanf("%d%d",&u,&v); 115 printf("%d\n",CAO(u,v,querySum,sum,0)); 116 }else if(op[1] == 'H'){ 117 scanf("%d%d",&u,&v); 118 update(loc[u],v,1); 119 }else if(op[1] == 'M'){ 120 scanf("%d%d",&u,&v); 121 printf("%d\n",CAO(u,v,queryMax,mymax,-0x3f3f3f3f)); 122 } 123 } 124 } 125 return 0; 126 } 127 /* 128 4 129 1 2 130 2 3 131 4 1 132 4 2 1 3 133 12 134 QMAX 3 4 135 QMAX 3 3 136 QMAX 3 2 137 QMAX 2 3 138 QSUM 3 4 139 QSUM 2 1 140 CHANGE 1 5 141 QMAX 3 4 142 CHANGE 3 6 143 QMAX 3 4 144 QMAX 2 4 145 QSUM 3 4 146 */
夜空中最亮的星,照亮我前行