[BZOJ3999] [TJOI2015]旅游

传送门

http://www.lydsy.com/JudgeOnline/problem.php?id=3999

题目大意

给定一棵树,树上有权值,要求支持
查询树上两点 a>b() 间路径上 max(xjxi) jai
以及路径整体 +c

题解

树链剖分+线段树合并
注意细节!!

const
    maxn=50040;
type
    data=record
    a1,a2,minn,maxx:longint; end;
var
    w:array[0..3*maxn,1..2]of longint;
    x,fa,son,size,dep,top,pos:array[0..maxn]of longint;
    seg:array[0..4*maxn,1..7]of longint;
    i,j,k:longint;
    n,m,len,a,b,c:longint;
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 swap(var a,b:longint);
var c:longint;
begin c:=a; a:=b; b:=c; end;

procedure init(a,b:longint);
begin
    w[len,1]:=b;
    if w[a,2]=0 then w[a,2]:=len else w[w[a,1],2]:=len;
    w[a,1]:=len; inc(len);
end;

procedure build(a,l,r:longint);
var mid:longint;
begin
    seg[a,1]:=l; seg[a,2]:=r; seg[a,3]:=0; seg[a,4]:=0; seg[a,5]:=0; seg[a,6]:=0; seg[a,7]:=0;
    if l=r then exit;
    mid:=(l+r)>>1;
    build(a<<1,l,mid); build(a<<1+1,mid+1,r);
end;

procedure pushdown(a:longint);
begin
    if seg[a,1]=seg[a,2] then begin seg[a,5]:=0; exit; end;
    inc(seg[a<<1,3],seg[a,5]); inc(seg[a<<1+1,3],seg[a,5]);
    inc(seg[a<<1,4],seg[a,5]); inc(seg[a<<1+1,4],seg[a,5]);
    inc(seg[a<<1,5],seg[a,5]); inc(seg[a<<1+1,5],seg[a,5]);
    seg[a,5]:=0;
end;

procedure update(a,l,r,c:longint);
var mid:longint;
begin
    if seg[a,5]<>0 then pushdown(a);
    if (seg[a,1]=l)and(seg[a,2]=r) then begin inc(seg[a,3],c); inc(seg[a,4],c); inc(seg[a,5],c); exit; end;
    mid:=(seg[a,1]+seg[a,2])>>1;
    if r<=mid then update(a<<1,l,r,c) else
    if l>mid then update(a<<1+1,l,r,c)
    else begin update(a<<1,l,mid,c); update(a<<1+1,mid+1,r,c); end;
    seg[a,3]:=min(seg[a<<1,3],seg[a<<1+1,3]);
    seg[a,4]:=max(seg[a<<1,4],seg[a<<1+1,4]);
    seg[a,6]:=max(max(seg[a<<1,6],seg[a<<1+1,6]),seg[a<<1,4]-seg[a<<1+1,3]);
    seg[a,7]:=max(max(seg[a<<1,7],seg[a<<1+1,7]),seg[a<<1+1,4]-seg[a<<1,3])
end;

function query(a,l,r:longint):data;
var mid:longint; t1,t2,ans:data;
begin
    if seg[a,5]<>0 then pushdown(a);
    if (seg[a,1]=l)and(seg[a,2]=r) then begin ans.minn:=seg[a,3]; ans.maxx:=seg[a,4]; ans.a1:=seg[a,6]; ans.a2:=seg[a,7]; exit(ans); end;
    mid:=(seg[a,1]+seg[a,2])>>1;
    if r<=mid then exit(query(a<<1,l,r)) else
    if l>mid then exit(query(a<<1+1,l,r))
    else
        begin  
            t1:=query(a<<1,l,mid); t2:=query(a<<1+1,mid+1,r);
            ans.minn:=min(t1.minn,t2.minn);
            ans.maxx:=max(t1.maxx,t2.maxx);
            ans.a1:=max(max(t1.a1,t2.a1),t1.maxx-t2.minn);
            ans.a2:=max(max(t1.a2,t2.a2),t2.maxx-t1.minn);
            exit(ans);
        end;
end;

procedure dfs1(a:longint);
var tt,v:longint;
begin
    tt:=w[a,2]; size[a]:=1; v:=0;
    while tt<>0 do
        begin
            if w[tt,1]<>fa[a]
            then
                begin
                    fa[w[tt,1]]:=a; dep[w[tt,1]]:=dep[a]+1;
                    dfs1(w[tt,1]);
                    inc(size[a],size[w[tt,1]]); if size[w[tt,1]]>size[v] then v:=w[tt,1];
                end;
            tt:=w[tt,2];
        end;
    son[a]:=v;
end;

procedure dfs2(a,pre:longint);
var tt:longint;
begin
    tt:=w[a,2]; inc(len); pos[a]:=len; top[a]:=pre; update(1,len,len,x[a]);
    if son[a]<>0 then dfs2(son[a],pre);
    while tt<>0 do
        begin
            if (w[tt,1]<>son[a])and(w[tt,1]<>fa[a]) then dfs2(w[tt,1],w[tt,1]);
            tt:=w[tt,2];
        end;
end;

procedure queryans(a,b,c:longint);
var t1,t2,tt:data;
begin
    t1.maxx:=0; t1.minn:=maxlongint; t1.a1:=0; t1.a2:=0;    
    t2.maxx:=0; t2.minn:=maxlongint; t2.a1:=0; t2.a2:=0;
    while top[a]<>top[b] do
        begin
            if dep[top[a]]>dep[top[b]]
            then
                begin
                    tt:=query(1,pos[top[a]],pos[a]);
                    t1.a1:=max(max(t1.a1,tt.a1),tt.maxx-t1.minn);
                    t1.maxx:=max(t1.maxx,tt.maxx);
                    t1.minn:=min(t1.minn,tt.minn);
                    update(1,pos[top[a]],pos[a],c);
                    a:=fa[top[a]];
                end
            else
                begin
                    tt:=query(1,pos[top[b]],pos[b]);
                    t2.a2:=max(max(t2.a2,tt.a2),t2.maxx-tt.minn);
                    t2.maxx:=max(t2.maxx,tt.maxx);
                    t2.minn:=min(t2.minn,tt.minn);
                    update(1,pos[top[b]],pos[b],c);
                    b:=fa[top[b]];
                end;                                    
        end;
    if dep[a]<dep[b]
    then
        begin
            tt:=query(1,pos[a],pos[b]);
            t2.a2:=max(max(t2.a2,tt.a2),t2.maxx-tt.minn);
            t2.maxx:=max(t2.maxx,tt.maxx);
            t2.minn:=min(t2.minn,tt.minn);
            writeln(max(max(t1.a1,t2.a2),t2.maxx-t1.minn));
            update(1,pos[a],pos[b],c);
        end
    else
        begin
            tt:=query(1,pos[b],pos[a]);
            t1.a1:=max(max(t1.a1,tt.a1),tt.maxx-t1.minn);
            t1.maxx:=max(t1.maxx,tt.maxx);
            t1.minn:=min(t1.minn,tt.minn);
            writeln(max(max(t1.a1,t2.a2),t2.maxx-t1.minn));
            update(1,pos[b],pos[a],c);
        end;
end;

begin
    readln(n); len:=n+1;
    for i:=1 to n do
        read(x[i]);
    for i:=1 to n-1 do
        begin
            readln(a,b);
            init(a,b); init(b,a);
        end;
    fa[1]:=0; dep[1]:=1; size[0]:=0; dfs1(1);
    len:=0; build(1,1,n); dfs2(1,1);
    readln(m);
    for i:=1 to m do
        begin
            readln(a,b,c);
            queryans(a,b,c);
        end;
end.

你可能感兴趣的:([BZOJ3999] [TJOI2015]旅游)