【题目描述】
Ray 乐忠于旅游,这次他来到了T 城。T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接。为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径。换句话说, T 城中只有N − 1 座桥。
Ray 发现,有些桥上可以看到美丽的景色,让人心情愉悦,但有些桥狭窄泥泞,令人烦躁。于是,他给每座桥定义一个愉悦度w,也就是说,Ray 经过这座桥会增加w 的愉悦度,这或许是正的也可能是负的。有时,Ray 看待同一座桥的心情也会发生改变。
现在,Ray 想让你帮他计算从u 景点到v 景点能获得的总愉悦度。有时,他还想知道某段路上最美丽的桥所提供的最大愉悦度,或是某段路上最糟糕的一座桥提供的最低愉悦度。
【输入格式】
输入的第一行包含一个整数N,表示T 城中的景点个数。景点编号为 0…N − 1。
接下来N − 1 行,每行三个整数u、v 和w,表示有一条u 到v,使 Ray 愉悦度增加w 的桥。桥的编号为1…N − 1。|w| <= 1000。 输入的第N + 1 行包含一个整数M,表示Ray 的操作数目。
接下来有M 行,每行描述了一个操作,操作有如下五种形式:
-
C i w,表示Ray 对于经过第i 座桥的愉悦度变成了w。
-
N u v,表示Ray 对于经过景点u 到v 的路径上的每一座桥的愉悦度都变成原来的相反数。
-
SUM u v,表示询问从景点u 到v 所获得的总愉悦度。
-
MAX u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最大愉悦度。
-
MIN u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最小愉悦度。
测试数据保证,任意时刻,Ray 对于经过每一座桥的愉悦度的绝对值小于等于1000。
【输出格式】
对于每一个询问(操作S、MAX 和MIN),输出答案。
S a m p l e    I n p u t Sample\;Input SampleInput
3
0 1 1
1 2 2
8
SUM 0 2
MAX 0 2
N 0 1
SUM 0 2
MIN 0 2
C 1 3
SUM 0 2
MAX 0 2
S a m p l e    O u t p u t Sample\;Output SampleOutput
3
2
1
-1
5
3
【题意分析】
码量真的很让人绝望。。。因为用pascal写的,我的码风写了380行左右。。。真tm毒瘤,加上debug的时间,如果现场我还不一定做得出来。。。
//380行,快跟RBT差不多了,这道题是真的zz
很神奇的一个地方:这次单点修改时没有去寻找数据存在了那个地方(参见我写的月下毛景树),直接上id[]
,就AC了,要是x经过which ()
之后(找深度更大的点)就过不了,这个问题值得研究。。。
之前的which ()
代码:
inline void which (int &x){
x <<= 1;
(depth[edge[x].from] < depth[edge[x].to])
? x = edge[x].to : x = edge[x].from;
}
对于这道题,维护三棵线段树:treeV[],treeMax,treeMin[]
,分别记录区间和,最大值,最小值。
pushdown也值得一提,因为是取反,那么很容易想到原来最大的取反之后变成最小的了,最小的取反之后变成最大的了,区间和的话直接取反。
序号从0开始,那么节点编号就直接+1,看着舒服。
Code:
type Front_Link_Star = record
from,tar,w,next : longint;
end;
const INF = 1 << 30;
MAXN = 300000;
var edge : array [-10..MAXN*2] of Front_Link_Star;
head : array [-10..MAXN*2] of longint;
lazy,treeV,treeMax,treeMin : array [-10..MAXN*4] of longint;
son,top,father,depth,id,rk,value,size : array [-10..MAXN] of longint;
dfn,cnt,n,q,i,x,y,z,k,ans,res : longint; s,opt : string;
Function max (x,y : longint) : longint;
begin
if x > y
then exit (x)
else exit (y);
end;
Function Min (x,y : longint) : longint;
begin
if x > y
then exit (y)
else exit (x);
end;
Procedure connect (x,y,z : longint);
begin
inc (cnt);
edge[cnt].from := x;
edge[cnt].tar := y;
edge[cnt].w := z;
edge[cnt].next := head[x];
head[x] := cnt;
end;
Procedure swap (var x,y : longint);
var temp : longint;
begin
temp := x; x := y; y := temp;
end;
//这去掉之后就AC了,不然样例都过不了
//Procedure which (var x : longint);
//begin
//x := x << 1;
//if (depth[edge[x].from] < depth[edge[x].tar])
// then x := edge[x].tar
// else x := edge[x].from;
//end;
//上传
Procedure pushup (now : longint);
begin
treeV[now] := treeV[now << 1] + treeV[now << 1 or 1];
treeMax[now] := max (treeMax[now << 1],treeMax[now << 1 or 1]);
treeMin[now] := min (treeMin[now << 1],treeMin[now << 1 or 1]);
end;
//pushdown是重点
Procedure pushdown (now : longint);
var lson,rson : longint;
begin
if lazy[now] <> 0
then begin
lson := now << 1; rson := now << 1 or 1;
swap (treeMin[lson],treeMax[lson]);
treeMin[lson] := -treeMin[lson];
treeMax[lson] := -treeMax[lson];
treeV[lson] := -treeV[lson];
lazy[lson] := lazy[lson] xor 1;
swap (treeMin[rson],treeMax[rson]);
treeMin[rson] := -treeMin[rson];
treeMax[rson] := -treeMax[rson];
treeV[rson] := -treeV[rson];
lazy[rson] := lazy[rson] xor 1;
lazy[now] := 0;
end;
end;
Procedure build (now,tl,tr : longint);
var mid : longint;
begin
lazy[now] := 0;
if tl = tr
then begin
treeV[now] := value[rk[tl]];
treeMax[now] := value[rk[tl]];
treeMin[now] := value[rk[tl]];
exit;
end;
mid := (tl + tr) >> 1;
build (now << 1,tl,mid);
build (now << 1 or 1,mid+1,tr);
pushup (now);
end;
//单点修改
Procedure updateChange (now,tl,tr,left,right,change : longint);
var mid : longint;
begin
if (right < tl) or (tr < left)
then exit;
if (left <= tl) and (tr <= right)
then begin
treeV[now] := change;
treeMax[now] := change;
treeMin[now] := change;
exit;
end;
pushdown (now);
mid := (tl + tr) >> 1;
updateChange (now << 1,tl,mid,left,right,change);
updateChange (now << 1 or 1,mid+1,tr,left,right,change);
pushup (now);
end;
//取反
Procedure updateReverse (now,tl,tr,left,right : longint);
var mid : longint;
begin
if (right < tl) or (tr < left)
then exit;
if (left <= tl) and (tr <= right)
then begin
swap (treeMin[now],treeMax[now]);
treeMin[now] := -treeMin[now];
treeMax[now] := -treeMax[now];
treeV[now] := -treeV[now];
lazy[now] := lazy[now] xor 1;
exit;
end;
pushdown (now);
mid := (tl + tr) >> 1;
updateReverse (now << 1,tl,mid,left,right);
updateReverse (now << 1 or 1,mid+1,tr,left,right);
pushup (now);
end;
Procedure queryV (now,tl,tr,left,right : longint);
var mid : longint;
begin
if (right < tl) or (tr < left)
then exit;
if (left <= tl) and (tr <= right)
then begin
inc (res,treeV[now]);
exit;
end;
pushdown (now);
mid := (tl + tr) >> 1;
queryV (now << 1,tl,mid,left,right);
queryV (now << 1 or 1,mid+1,tr,left,right);
pushup (now);
end;
Procedure queryMax (now,tl,tr,left,right : longint);
var mid : longint;
begin
if (right < tl) or (tr < left)
then exit;
if (left <= tl) and (tr <= right)
then begin
res := max (res,treeMax[now]);
exit;
end;
pushdown (now);
mid := (tl + tr) >> 1;
queryMax (now << 1,tl,mid,left,right);
queryMax (now << 1 or 1,mid+1,tr,left,right);
pushup (now);
end;
Procedure queryMin (now,tl,tr,left,right : longint);
var mid : longint;
begin
if (right < tl) or (tr < left)
then exit;
if (left <= tl) and (tr <= right)
then begin
res := min (res,treeMin[now]);
exit;
end;
pushdown (now);
mid := (tl + tr) >> 1;
queryMin (now << 1,tl,mid,left,right);
queryMin (now << 1 or 1,mid+1,tr,left,right);
pushup (now);
end;
//Modify_Range
Procedure MR (x,y : longint);
begin
while top[x] <> top[y] do
begin
if (depth[top[x]] < depth[top[y]])
then swap (x,y);
updateReverse (1,1,n,id[top[x]],id[x]);
x := father[top[x]];
end;
if x = y
then exit;
if depth[x] > depth[y]
then swap (x,y);
updateReverse (1,1,n,id[x]+1,id[y]);
end;
//Query_Range_Value
Procedure QRV (x,y : longint);
begin
while top[x] <> top[y] do
begin
if (depth[top[x]] < depth[top[y]])
then swap (x,y);
res := 0;
queryV (1,1,n,id[top[x]],id[x]);
inc (ans,res);
x := father[top[x]];
end;
if x = y
then exit;
if depth[x] > depth[y]
then swap (x,y);
res := 0;
queryV (1,1,n,id[x]+1,id[y]);
inc (ans,res);
end;
//Query_Range_Min
Procedure QRMin (x,y : longint);
begin
while top[x] <> top[y] do
begin
if (depth[top[x]] < depth[top[y]])
then swap (x,y);
res := INF;
queryMin (1,1,n,id[top[x]],id[x]);
ans := min (ans,res);
x := father[top[x]];
end;
if x = y
then exit;
if depth[x] > depth[y]
then swap (x,y);
res := INF;
queryMin (1,1,n,id[x]+1,id[y]);
ans := min (ans,res);
end;
//Query_Range_Max
Procedure QRMax (x,y : longint);
begin
while top[x] <> top[y] do
begin
if (depth[top[x]] < depth[top[y]])
then swap (x,y);
res := -INF;
queryMax (1,1,n,id[top[x]],id[x]);
ans := max (ans,res);
x := father[top[x]];
end;
if x = y
then exit;
if depth[x] > depth[y]
then swap (x,y);
res := -INF;
queryMax (1,1,n,id[x]+1,id[y]);
ans := max (ans,res);
end;
Procedure DFS1 (now,fa,d : longint);
var maxson,v,i : longint;
begin
father[now] := fa;
depth[now] := d;
size[now] := 1;
maxson := -1;
i := head[now];
while i <> 0 do
begin
v := edge[i].tar;
if v = fa
then begin
i := edge[i].next;
continue;
end;
DFS1 (v,now,d+1);
value[v] := edge[i].w;
inc (size[now],size[v]);
if size[v] > maxson
then begin
son[now] := v;
maxson := size[v];
end;
i := edge[i].next;
end;
end;
Procedure DFS2 (now,top_heavy : longint);
var v,i : longint;
begin
top[now] := top_heavy;
inc (dfn);
id[now] := dfn;
rk[dfn] := now;
if (son[now] = 0)
then exit;
DFS2 (son[now],top_heavy);
i := head[now];
while i <> 0 do
begin
v := edge[i].tar;
if (v <> father[now]) and (v <> son[now])
then DFS2 (v,v);
i := edge[i].next;
end;
end;
begin
readln (n);
for i := 1 to n-1 do
begin
readln (x,y,z);
inc (x); inc (y);
connect (x,y,z);
connect (y,x,z);
end;
DFS1 (1,0,1);
DFS2 (1,1);
build (1,1,n);
readln (q);
for i := 1 to q do
begin
readln (s);
k := pos (' ',s);
opt := copy (s,1,k-1);
delete (s,1,k);
k := pos (' ',s);
val (copy (s,1,k-1),x);
val (copy (s,k+1,length (s)-k),y);
if opt = 'SUM'
then begin
inc (x); inc (y);
ans := 0;
QRV (x,y);
writeln (ans);
end;
if opt = 'MAX'
then begin
inc (x); inc (y);
ans := -INF;
QRMax (x,y);
writeln (ans);
end;
if opt = 'MIN'
then begin
inc (x); inc (y);
ans := INF;
QRMin (x,y);
writeln (ans);
end;
if opt = 'C'
then begin
inc (x);
//which (x);
updateChange (1,1,n,id[x],id[x],y);
end;
if opt = 'N'
then begin
inc (x); inc (y);
MR (x,y);
end;
end;
//return 0;
end.