[BZOJ3626] [LNOI2014]LCA

传送门

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

题目大意

给定一棵树,询问 bi=adep[lca(i,c)]

题解

ORZ
我们先考虑可以怎么求两个点的 lca 的深度,我们对其中一个到根上的所有点都+1,然后查询另一个点到根的所有点权和即可
然后对于本题的所有询问 [L,R] 都可以拆成 [1,L1][1,R] 这样我们离线把查询排序,依次把 1 ~ n 到根路径都+1然后查询即可

const
    maxn=50005;
var
    w:array[0..3*maxn,1..2]of longint;
    x:array[0..2*maxn,1..4]of longint;
    seg:array[0..4*maxn,1..4]of longint;
    fa,son,size,dep,top,pos:array[0..maxn]of longint;
    ans:array[0..maxn]of int64;
    i,j,k:longint;
    n,m,len,a,b,c,now:longint;
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 sort(l,r:longint);
var i,j,a,b,c,d:longint;
begin
    i:=l; j:=r; a:=x[(l+r)div 2,1]; b:=x[(l+r)div 2,2];
    repeat
        while (x[i,1]<a)or((x[i,1]=a)and(x[i,2]<b)) do inc(i);
        while (x[j,1]>a)or((x[j,1]=a)and(x[j,2]>b)) do dec(j);
        if not(i>j) then
        begin
            d:=1; c:=x[i,d]; x[i,d]:=x[j,d]; x[j,d]:=c;
            d:=2; c:=x[i,d]; x[i,d]:=x[j,d]; x[j,d]:=c;
            d:=3; c:=x[i,d]; x[i,d]:=x[j,d]; x[j,d]:=c;
            d:=4; c:=x[i,d]; x[i,d]:=x[j,d]; x[j,d]:=c;
            inc(i); dec(j);
        end;
    until i>j;
    if l<j then sort(l,j);
    if i<r then sort(i,r);
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 fa[a]<>w[tt,1]
            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;
    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 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;
    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,4]:=0; exit; end;
    inc(seg[a<<1,4],seg[a,4]); inc(seg[a<<1,3],seg[a,4]*(seg[a<<1,2]-seg[a<<1,1]+1));
    inc(seg[a<<1+1,4],seg[a,4]); inc(seg[a<<1+1,3],seg[a,4]*(seg[a<<1+1,2]-seg[a<<1+1,1]+1));
    seg[a,4]:=0;
end;

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

function query(a,l,r:longint):longint;
var mid:longint;
begin
    if seg[a,4]<>0 then pushdown(a);
    if (l=seg[a,1])and(r=seg[a,2]) then exit(seg[a,3]);
    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 exit(query(a<<1,l,mid)+query(a<<1+1,mid+1,r)); 
end;

procedure change(a,b:longint);
begin
    while top[a]<>top[b] do
        begin
            if dep[top[a]]<dep[top[b]] then swap(a,b);
            update(1,pos[top[a]],pos[a]);
            a:=fa[top[a]];
        end;
    if dep[a]>dep[b] then swap(a,b);
    update(1,pos[a],pos[b]);
end;

function queryans(a,b:longint):int64;
var c:longint; ans:int64;
begin
    ans:=0;
    while top[a]<>top[b] do
        begin
            if dep[top[a]]<dep[top[b]] then swap(a,b);
            c:=query(1,pos[top[a]],pos[a]); inc(ans,c);
            a:=fa[top[a]];
        end;
    if dep[a]>dep[b] then swap(a,b);
    c:=query(1,pos[a],pos[b]); inc(ans,c);
    exit(ans);
end;

begin
    readln(n,m); len:=n+1;
    for i:=2 to n do
        begin
            readln(a); inc(a);
            init(a,i); init(i,a);
        end;
    len:=0;
    for i:=1 to m do
        begin
            readln(a,b,c); inc(a); inc(b); inc(c);
            inc(len); x[len,1]:=a-1; x[len,2]:=c; x[len,3]:=i; x[len,4]:=-1;
            inc(len); x[len,1]:=b; x[len,2]:=c; x[len,3]:=i; x[len,4]:=1;
        end;
    sort(1,len); {x[i,1] x[i,2]} x[0,1]:=len;
    build(1,1,n);
    dep[1]:=1; fa[1]:=0; size[0]:=0; dfs1(1);
    len:=0; dfs2(1,1); now:=0;
    for i:=1 to x[0,1] do
        begin
            for j:=now+1 to x[i,1] do             
                change(1,j);
            now:=x[i,1];
            ans[x[i,3]]:=ans[x[i,3]]+queryans(1,x[i,2])*x[i,4];
        end;
    for i:=1 to m do
        writeln(ans[i] mod 201314);
end.

你可能感兴趣的:([BZOJ3626] [LNOI2014]LCA)