1036: [ZJOI2008]树的统计Count
1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 7496 Solved: 3078
[Submit][Status][Discuss]
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
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
2
2
10
6
5
6
5
16
HINT
Source
题解:phile神犇推荐的链剖模板题,一直不知道为啥挂掉,急死掉= =,最后发现居然把inline去掉就A了QAQ,逗我= =
事实证明——(引用phile神犇的原话)黑科技不可滥用TT
1 type 2 point=^node; 3 node=record 4 g:longint; 5 next:point; 6 end; 7 var 8 i,j,k,l,m,n,tot,root:longint;a1:int64; 9 a:array[0..100000] of point;ch:char; 10 d,e:array[0..500000] of int64; 11 len,son,siz,top,list,f,num,anum:array[0..100000] of longint; 12 c:array[0..20,0..100000] of longint; 13 function min(x,y:longint):longint; 14 begin 15 if x<y then min:=x else min:=y; 16 end; 17 function max(x,y:longint):longint; 18 begin 19 if x>y then max:=x else max:=y; 20 end; 21 procedure swap(var x,y:longint); 22 var z:longint; 23 begin 24 z:=x;x:=y;y:=z; 25 end; 26 procedure add(x,y:longint); 27 var p:point; 28 begin 29 new(p);p^.g:=y;p^.next:=a[x];a[x]:=p; 30 end; 31 procedure dfs(y,x:longint); 32 var p:point; 33 begin 34 c[0,x]:=y;siz[x]:=1;len[x]:=len[y]+1;son[x]:=0; 35 p:=a[x]; 36 while p<>nil do 37 begin 38 if p^.g<>y then 39 begin 40 dfs(x,p^.g); 41 inc(siz[x],siz[p^.g]); 42 if (son[x]=0) or (siz[p^.g]>siz[son[x]]) then son[x]:=p^.g; 43 end; 44 p:=p^.next; 45 end; 46 end; 47 procedure dfs2(y,x,z:longint); 48 var p:point; 49 begin 50 top[x]:=z;inc(tot);num[x]:=tot;anum[tot]:=x; 51 if son[x]<>0 then dfs2(x,son[x],z);p:=a[x]; 52 while p<>nil do 53 begin 54 if (p^.g<>y) and (p^.g<>son[x]) then dfs2(x,p^.g,p^.g); 55 p:=p^.next; 56 end; 57 end; 58 procedure built(z,x,y:longint); 59 begin 60 if x=y then 61 begin 62 list[x]:=z; 63 d[z]:=f[anum[x]]; 64 e[z]:=d[z]; 65 end 66 else 67 begin 68 built(z*2,x ,(x+y) div 2); 69 built(z*2+1,(x+y) div 2+1,y); 70 d[z]:=d[z*2]+d[z*2+1]; 71 if e[z*2+1]>e[z*2] then e[z]:=e[z*2+1] else e[z]:=e[z*2]; 72 end; 73 end; 74 procedure change(x:longint;y:int64); 75 begin 76 x:=list[x];d[x]:=y;e[x]:=y;x:=x div 2; 77 while x>0 do 78 begin 79 d[x]:=d[x*2]+d[x*2+1]; 80 if e[x*2+1]>e[x*2] then e[x]:=e[x*2+1] else e[x]:=e[x*2]; 81 x:=x div 2; 82 end; 83 end; 84 function sum(z,x,y,l,r:longint):int64; 85 begin 86 if l>r then exit(0); 87 if (x=l) and (y=r) then exit(d[z]); 88 exit(sum(z*2,x,(x+y) div 2,l,min(r,(x+y) div 2))+sum(z*2+1,(x+y) div 2+1,y,max((x+y) div 2+1,l),r)); 89 end; 90 function getmax(z,x,y,l,r:longint):int64; 91 var a1,a2:int64; 92 begin 93 if l>r then exit(-maxlongint*maxlongint); 94 if (x=l) and (y=r) then exit(e[z]); 95 a1:=getmax(z*2,x,(x+y) div 2,l,min(r,(x+y) div 2)); 96 a2:=getmax(z*2+1,(x+y) div 2+1,y,max((x+y) div 2+1,l),r); 97 if a1>a2 then exit(a1) else exit(a2); 98 end; 99 function getup(x,y:longint):longint; 100 var i:longint; 101 begin 102 i:=0; 103 while y>0 do 104 begin 105 if odd(y) then x:=c[i,x]; 106 inc(i);y:=y div 2; 107 end; 108 exit(x); 109 end; 110 function getcom(x,y:longint):longint; 111 var i:longint; 112 begin 113 if len[x]<len[y] then swap(x,y); 114 x:=getup(x,len[x]-len[y]); 115 if x=y then exit(x); 116 for i:=trunc(round(ln(len[x])/ln(2))) downto 0 do 117 if c[i,x]<>c[i,y] then 118 begin 119 x:=c[i,x]; 120 y:=c[i,y]; 121 end; 122 exit(c[0,x]); 123 end; 124 procedure treechange(x:longint;y:int64); 125 begin 126 change(num[x],y); 127 end; 128 function treesum(x,y:longint):int64; 129 var i,z:longint; 130 begin 131 z:=getcom(x,y);treesum:=0; 132 repeat 133 if len[top[x]]<len[z] then i:=z else i:=top[x]; 134 inc(treesum,sum(1,1,n,num[i],num[x])); 135 if i=z then break; 136 x:=c[0,i]; 137 until false; 138 repeat 139 if len[top[y]]<len[z] then i:=z else i:=top[y]; 140 inc(treesum,sum(1,1,n,num[i],num[y])); 141 if i=z then break; 142 y:=c[0,i]; 143 until false; 144 dec(treesum,sum(1,1,n,num[z],num[z])); 145 end; 146 function treemax(x,y:longint):int64; 147 var i,z:longint;a1:int64; 148 begin 149 treemax:=-maxlongint*maxlongint; 150 z:=getcom(x,y); 151 repeat 152 if len[top[x]]<len[z] then i:=z else i:=top[x]; 153 a1:=getmax(1,1,n,num[i],num[x]); 154 if a1>treemax then treemax:=a1; 155 if i=z then break; 156 x:=c[0,i]; 157 until false; 158 repeat 159 if len[top[y]]<len[z] then i:=z else i:=top[y]; 160 a1:=getmax(1,1,n,num[i],num[y]); 161 if a1>treemax then treemax:=a1; 162 if i=z then break; 163 y:=c[0,i]; 164 until false; 165 end; 166 begin 167 readln(n); 168 for i:=1 to n do a[i]:=nil; 169 for i:=1 to n-1 do 170 begin 171 readln(j,k); 172 add(j,k);add(k,j); 173 end; 174 for i:=1 to n do read(f[i]);readln; 175 root:=random(n)+1;dfs(0,root);dfs2(0,root,root); 176 for i:=1 to trunc(round(ln(n)/ln(2)))+1 do 177 for j:=1 to n do 178 c[i,j]:=c[i-1,c[i-1,j]]; 179 built(1,1,n); 180 readln(m); 181 for i:=1 to m do 182 begin 183 read(ch,ch); 184 case upcase(ch) of 185 'M':begin 186 readln(ch,ch,j,k); 187 writeln(treemax(j,k)); 188 end; 189 'S':begin 190 readln(ch,ch,j,k); 191 writeln(treesum(j,k)); 192 end; 193 'H':begin 194 readln(ch,ch,ch,ch,j,a1); 195 treechange(j,a1); 196 end; 197 end; 198 end; 199 readln; 200 end.