关于边剖

  之前做的大多是点剖,其实转换到边剖非常简单。

  我的做法是每个点的点权记录其到父亲节点的边的边权。

  只要solve的时候不要把最上面的点记录在内就可以了。


  这道题除了边剖之外另一个难点是处理NEGATE操作

  将从a到b路径上的边权都取反

  其实思考一下便知只要存mx和mn两个值然后反转的时候互换并取反就可以了

  但是出现了问题,我以前用的向下传递不对了

  因为反转操作的存在,当前的值很可能被子节点中本来并不优秀但是反转了之后能比当前点更好的点取代

  然而传统的情况下当(tr[p].l=l)and(tr[p].r=r)的时候就停止了

  这就导致了可能当前的状态并不是最优秀的

  我们用一个push操作先向下传递一遍并刷新当前的值

  保证当前p节点里的值都是真实存在的

  在每个过程里都先执行一次push操作

  时间复杂度看上去或许并不乐观,但是实际上标记为真的个数并不多

  像这样特殊的操作就需要这种保证正确性的传递方式

  以后遇到类似的题要多加思考

  (树链剖分的题代码量真的很大啊QAQ

 program poj3237;
const maxn=;maxm=;
var test,t,x,y,z,cnt,tt,n,m,j,i:longint;
son,size,link,belong,deep,v,pos:array[-..maxn]of longint;
ter,next,w:array[-..maxm]of longint;
fa:array[-..maxn,-..]of longint;
tr:array[-..*maxn]of record l,r,mx,mi:longint;wait,op:boolean;end;
ch:char; function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end; function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end; procedure add(x,y,z:longint);
begin
inc(j);ter[j]:=y;next[j]:=link[x];link[x]:=j;w[j]:=z;
inc(j);ter[j]:=x;next[j]:=link[y];link[y]:=j;w[j]:=z;
end; procedure dfs1(p:longint);
var i,j:longint;
begin
size[p]:=;
for i:= to do
begin
if deep[p]<= << i then break;
fa[p][i]:=fa[fa[p][i-]][i-];
end;
j:=link[p];
while j<> do
begin
if deep[ter[j]]= then
begin
deep[ter[j]]:=deep[p]+;
fa[ter[j]][]:=p;
v[ter[j]]:=w[j];son[(j+) >> ]:=ter[j];
dfs1(ter[j]);
inc(size[p],size[ter[j]]);
end;
j:=next[j];
end;
end; procedure dfs2(p,chain:longint);
var j,k:longint;
begin
inc(cnt);pos[p]:=cnt;belong[p]:=chain;
k:=;
j:=link[p];
while j<> do
begin
if deep[ter[j]]>deep[p] then
if size[ter[j]]>size[k] then k:=ter[j];
j:=next[j];
end;
if k= then exit;
dfs2(k,chain);
j:=link[p];
while j<> do
begin
if (deep[ter[j]]>deep[p])and(ter[j]<>k) then dfs2(ter[j],ter[j]);
j:=next[j];
end;
end; procedure build(p,l,r:longint);
var mid:longint;
begin
tr[p].l:=l;tr[p].r:=r;tr[p].mx:=-maxlongint;tr[p].mi:=maxlongint;tr[p].wait:=false;tr[p].op:=false;
if l=r then exit;
mid:=(l+r) >> ;
build(p << ,l,mid);
build(p << +,mid+,r);
end; procedure push(p:longint);
var tem:longint;
begin
if tr[p].l=tr[p].r then exit;
if tr[p].wait then
begin
push(p << );push(p << +);
tr[p << ].mx:=max(tr[p].mx,tr[p << ].mx);tr[p << ].mi:=min(tr[p << ].mi,tr[p].mi);tr[p << ].wait:=true;
tr[p << +].mx:=max(tr[p].mx,tr[p << +].mx);tr[p << +].mi:=min(tr[p << +].mi,tr[p].mi);tr[p << +].wait:=true;
tr[p].mx:=max(tr[p << ].mx,tr[p << +].mx);
tr[p].mi:=min(tr[p << ].mi,tr[p << +].mi);
tr[p].wait:=false;
end;
if tr[p].op then
begin
push(p << );push(p << +);
tem:=tr[p << ].mx;tr[p << ].mx:=-tr[p << ].mi;tr[p << ].mi:=-tem;tr[p << ].op:=true;
tem:=tr[p << +].mx;tr[p << +].mx:=-tr[p << +].mi;tr[p << +].mi:=-tem;tr[p << +].op:=true;
tr[p].mx:=max(tr[p << ].mx,tr[p << +].mx);
tr[p].mi:=min(tr[p << ].mi,tr[p << +].mi);
tr[p].op:=false;
end;
end; procedure insert(p,l,r,ave:longint);
var mid,tem:longint;
begin
push(p);
if (tr[p].l=l)and(tr[p].r=r) then
begin
tr[p].mx:=ave;
tr[p].mi:=ave;
tr[p].wait:=true;
exit;
end;
mid:=(tr[p].l+tr[p].r) >> ;
if r<=mid then insert(p << ,l,r,ave) else
if l>mid then insert(p << +,l,r,ave) else
begin
insert(p << ,l,mid,ave);
insert(p << +,mid+,r,ave);
end;
tr[p].mx:=max(tr[p << ].mx,tr[p << +].mx);
tr[p].mi:=min(tr[p << ].mi,tr[p << +].mi);
end; function lca(x,y:longint):longint;
var tem,i:longint;
begin
if deep[x]<deep[y] then
begin
tem:=x;x:=y;y:=tem;
end;
if deep[x]<>deep[y] then
begin
i:=trunc(ln(deep[x]-deep[y])/ln());
while deep[x]>deep[y] do
begin
while deep[x]-deep[y]>= << i do x:=fa[x][i];
dec(i);
end;
end;
if x=y then exit(x);
i:=trunc(ln(n)/ln());
while fa[x][]<>fa[y][] do
begin
while fa[x][i]<>fa[y][i] do
begin
x:=fa[x][i];y:=fa[y][i];
end;
dec(i);
end;
exit(fa[x][]);
end; function query(p,l,r:longint):longint;
var mid,tem:longint;
begin
push(p);
if (tr[p].l=l)and(tr[p].r=r) then exit(tr[p].mx);
mid:=(tr[p].l+tr[p].r) >> ;
if r<=mid then exit(query(p << ,l,r)) else
if l>mid then exit(query(p << +,l,r)) else
exit(max(query(p << ,l,mid),query(p << +,mid+,r)));
end; procedure dop(p,l,r:longint);
var mid,tem:longint;
begin
push(p);
if (tr[p].l=l)and(tr[p].r=r) then
begin
tem:=tr[p].mx;tr[p].mx:=-tr[p].mi;tr[p].mi:=-tem;
tr[p].op:=true;
exit;
end;
mid:=(tr[p].l+tr[p].r) >> ;
if r<=mid then dop(p << ,l,r) else
if l>mid then dop(p << +,l,r) else
begin
dop(p << ,l,mid);
dop(p << +,mid+,r);
end;
tr[p].mx:=max(tr[p << ].mx,tr[p << +].mx);
tr[p].mi:=min(tr[p << ].mi,tr[p << +].mi);
end; function solve(x,y:longint):longint;
var mx:longint;
begin
mx:=-maxlongint;
while belong[x]<>belong[y] do
begin
mx:=max(mx,query(,pos[belong[x]],pos[x]));
x:=fa[belong[x]][];
end;
if x<>y then mx:=max(mx,query(,pos[y]+,pos[x]));
exit(mx);
end; procedure mend(x,y:longint);
begin
while belong[x]<>belong[y] do
begin
dop(,pos[belong[x]],pos[x]);
x:=fa[belong[x]][];
end;
if x<>y then dop(,pos[y]+,pos[x]);
end; begin
readln(test);
for tt:= to test do
begin
readln;
readln(n);j:=;
fillchar(link,sizeof(link),);
fillchar(next,sizeof(next),);
fillchar(deep,sizeof(deep),);
fillchar(fa,sizeof(fa),);
for i:= to n- do
begin
readln(x,y,z);
add(x,y,z);
end;
deep[]:=;dfs1();
cnt:=;dfs2(,);
build(,,n);
for i:= to n do insert(,pos[i],pos[i],v[i]);
read(ch);
while ch<>'D' do
begin
if ch='Q' then
begin
readln(ch,ch,ch,ch,x,y);
t:=lca(x,y);
writeln(max(solve(x,t),solve(y,t)));
end else
if ch='N' then
begin
readln(ch,ch,ch,ch,ch,x,y);
t:=lca(x,y);
mend(x,t);mend(y,t);
end else
begin
readln(ch,ch,ch,ch,ch,x,y);
insert(,pos[son[x]],pos[son[x]],y);
end;
read(ch);
end;
readln;
end;
end.
05-06 19:32