[BZOJ3531] [SDOI2014] 旅行

传送门

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

题目大意

给定一棵树,每个点有一个权值和一个颜色,多次改变一些点的权值和颜色,多次求一条路径上与起点和终点颜色相同的点的权值和以及权值最大值

题解

按照颜色建颜色种类棵线段树,当然明显内存承受不了,所以我们动态开点,不明白的看代码

const
    maxn=100050;
var
    w:array[0..3*maxn,1..2]of longint;
    ls,rs,summ,maxx:array[0..20*maxn]of longint;
    x,y,size,fa,dep,son,top,pos,root:array[0..maxn]of longint;
    i,j,k:longint;
    n,m,len,tot,a,b:longint;
    c1,c2:char; st:string;
function max(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 dfs1(a:longint); {fa,size,son,dep}
var tt,v:longint;
begin
    tt:=w[a,2]; v:=0; size[a]:=1;
    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); {top,pos}
var tt:longint;
begin
    tt:=w[a,2]; inc(len); pos[a]:=len; top[a]:=pre;
    if son[a]<>0 then dfs2(son[a],pre);
    while tt<>0 do
        begin
            if (w[tt,1]<>fa[a])and(w[tt,1]<>son[a]) then dfs2(w[tt,1],w[tt,1]);
            tt:=w[tt,2];
        end;
end;

procedure insert(var a:longint; l,r,b,val:longint);
var mid:longint;
begin
    if a=0 then begin inc(tot); a:=tot; end;
    inc(summ[a],val); maxx[a]:=max(maxx[a],val);
    if l=r then exit;
    mid:=(l+r)>>1;
    if b<=mid
    then insert(ls[a],l,mid,b,val)
    else insert(rs[a],mid+1,r,b,val);
end;

procedure update(var a:longint; l,r,b,val:longint);
var mid:longint;
begin
    if a=0 then begin inc(tot); a:=tot; end;
    inc(summ[a],val);
    if l=r then begin inc(maxx[a],val); exit; end;
    mid:=(l+r)>>1;
    if b<=mid
    then update(ls[a],l,mid,b,val)
    else update(rs[a],mid+1,r,b,val);
    maxx[a]:=max(maxx[ls[a]],maxx[rs[a]]);
end;

function querysum(a,l,r,b,c:longint):longint;
var mid:longint;
begin
    if (l=b)and(r=c) then exit(summ[a]);
    mid:=(b+c)>>1;
    if r<=mid then exit(querysum(ls[a],l,r,b,mid)) else
    if l>mid then exit(querysum(rs[a],l,r,mid+1,c))
    else exit(querysum(ls[a],l,mid,b,mid)+querysum(rs[a],mid+1,r,mid+1,c));
end;

function querymax(a,l,r,b,c:longint):longint;
var mid:longint;
begin
    if (l=b)and(r=c) then exit(maxx[a]);
    mid:=(b+c)>>1;
    if r<=mid then exit(querymax(ls[a],l,r,b,mid)) else
    if l>mid then exit(querymax(rs[a],l,r,mid+1,c))
    else exit(max(querymax(ls[a],l,mid,b,mid),querymax(rs[a],mid+1,r,mid+1,c)));
end;

procedure cc;
begin
    readln(a,b);
    update(root[y[a]],1,n,pos[a],-x[a]);
    y[a]:=b;
    insert(root[y[a]],1,n,pos[a],x[a]);
end;

procedure cw;
begin
    readln(a,b);
    update(root[y[a]],1,n,pos[a],b-x[a]);
    x[a]:=b;
end;

procedure qs;
var kind,ans:longint;
begin
    readln(a,b); kind:=y[a]; ans:=0;
    while top[a]<>top[b] do
        begin
            if dep[top[a]]<dep[top[b]] then swap(a,b);
            inc(ans,querysum(root[kind],pos[top[a]],pos[a],1,n));
            a:=fa[top[a]];
        end;
    if dep[a]>dep[b] then swap(a,b);
    inc(ans,querysum(root[kind],pos[a],pos[b],1,n));
    writeln(ans);
end;

procedure qm;
var kind,ans:longint;
begin
    readln(a,b); kind:=y[a]; ans:=-maxlongint;
    while top[a]<>top[b] do
        begin
            if dep[top[a]]<dep[top[b]] then swap(a,b);
            ans:=max(ans,querymax(root[kind],pos[top[a]],pos[a],1,n));
            a:=fa[top[a]];
        end;
    if dep[a]>dep[b] then swap(a,b);
    ans:=max(ans,querymax(root[kind],pos[a],pos[b],1,n));
    writeln(ans);       
end;

begin
    readln(n,m); len:=n+1;
    for i:=1 to n do
        readln(x[i],y[i]);
    for i:=1 to n-1 do
        begin readln(a,b); init(a,b); init(b,a); end;
    dep[1]:=1; size[0]:=0;
    dfs1(1);
    len:=0;
    dfs2(1,1);
    tot:=0; summ[0]:=0; maxx[0]:=0;
    for i:=1 to n do
        insert(root[y[i]],1,n,pos[i],x[i]);
    for i:=1 to m do
        begin
            read(c1,c2);
            case c2 of
            'C':cc;
            'W':cw;
            'S':qs;
            'M':qm;
            end;
        end;
end.

你可能感兴趣的:([BZOJ3531] [SDOI2014] 旅行)