码迷,mamicode.com
首页 > 其他好文 > 详细

[BZOJ2243][SDOI2011]染色 解题报告|树链剖分

时间:2015-04-11 08:55:39      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:

Description

 

给定一棵有n个节点的无根树和m个操作,操作有2类:

1、将节点a到节点b路径上所有点都染成颜色c;

2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”3段组成:“11”、“222”和“1”

请你写一个程序依次完成这m个操作。

  与上一题差别不大,主要就是solve过程要根据左端点和右端点的颜色处理合并时候的情况

  线段树的每个节点要记录颜色段数|最左边的颜色|最右边的颜色

  同时往下传的时候标记要做好(之前那道题是单点修改所以不用考虑下传

  因为这个昨晚调了一个晚上无果...果然是早上头脑清醒的多 一下子就改好了...

program bzoj2243;
const maxn=1000010;maxm=2000010;
var ter,next:array[-1..maxm]of longint;
    link,pos,deep,size,belong,v:array[-1..maxn]of longint;
    fa:array[-1..maxn,-1..20]of longint;
    cnt,n,m,i,j,x,y,z,t:longint;
    ch:char;
    tr:array[-1..5*maxn]of record l,r,lc,rc,cover:longint;wait:boolean;end;

procedure add(x,y:longint);
begin
    inc(j);ter[j]:=y;next[j]:=link[x];link[x]:=j;
    inc(j);ter[j]:=x;next[j]:=link[y];link[y]:=j;
end;

procedure dfs1(p:longint);
var i,j:longint;
begin
    size[p]:=1;
    for i:=1 to 17 do
    begin
        if deep[p]<=1 << i then break;
        fa[p][i]:=fa[fa[p][i-1]][i-1];
    end;
    j:=link[p];
    while j<>0 do
    begin
        if deep[ter[j]]=0 then
        begin
            deep[ter[j]]:=deep[p]+1;
            fa[ter[j]][0]:=p;
            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:=0;
    j:=link[p];
    while j<>0 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=0 then exit;
    dfs2(k,chain);
    j:=link[p];
    while j<>0 do
    begin
        if (deep[ter[j]]>deep[p])and(k<>ter[j]) 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].cover:=1;tr[p].lc:=-1;tr[p].rc:=-1;
    if l=r then exit;
    mid:=(l+r) >> 1;
    build(p << 1,l,mid);
    build(p << 1+1,mid+1,r);
end;

procedure insert(p,l,r,x:longint);
var mid:longint;
begin
    if (tr[p].l=l)and(tr[p].r=r) then
    begin
        tr[p].cover:=1;tr[p].lc:=x;tr[p].rc:=x;tr[p].wait:=true;
        exit;
    end;
    mid:=(tr[p].l+tr[p].r) >> 1;
    if tr[p].wait then
    begin
        tr[p << 1].cover:=1;tr[p << 1].lc:=tr[p].lc;tr[p << 1].rc:=tr[p].rc;
        tr[p << 1+1].cover:=1;tr[p << 1+1].lc:=tr[p].lc;tr[p << 1+1].rc:=tr[p].rc;
        tr[p].wait:=false;
                tr[p << 1].wait:=true;tr[p << 1+1].wait:=true;
    end;
    if r<=mid then insert(p << 1,l,r,x) else
        if l>mid then insert(p << 1+1,l,r,x) else
        begin
            insert(p << 1,l,mid,x);
            insert(p << 1+1,mid+1,r,x);
        end;
        tr[p].cover:=tr[p << 1].cover+tr[p << 1+1].cover;
    if tr[p << 1].rc=tr[p << 1+1].lc then dec(tr[p].cover);
    tr[p].lc:=tr[p << 1].lc;tr[p].rc:=tr[p << 1+1].rc;
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(2));
        while deep[x]<>deep[y] do
        begin
            while (deep[x]-deep[y]>=1 << i) do x:=fa[x][i];
            dec(i);
        end;
    end;
    if x=y then exit(x);
    i:=trunc(ln(n)/ln(2));
    while fa[x][0]<>fa[y][0] 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,0]);
end;

procedure query(p,l,r:longint;var lc,rc,ave:longint);
var mid,ll,rr,x,tem:longint;
begin
    if (tr[p].l=l)and(tr[p].r=r) then
    begin
        lc:=tr[p].lc;rc:=tr[p].rc;
        ave:=tr[p].cover;
                exit;
        end;
    mid:=(tr[p].l+tr[p].r) >> 1;
        if tr[p].wait then
    begin
        tr[p << 1].cover:=1;tr[p << 1].lc:=tr[p].lc;tr[p << 1].rc:=tr[p].rc;
        tr[p << 1+1].cover:=1;tr[p << 1+1].lc:=tr[p].lc;tr[p << 1+1].rc:=tr[p].rc;
        tr[p].wait:=false;
                tr[p << 1].wait:=true;tr[p << 1+1].wait:=true;
    end;
    if r<=mid then query(p << 1,l,r,lc,rc,ave) else
        if l>mid then query(p << 1+1,l,r,lc,rc,ave) else
        begin
            query(p << 1,l,mid,lc,ll,ave);
            query(p << 1+1,mid+1,r,rr,rc,tem);
                        inc(ave,tem);
            if ll=rr then dec(ave);
        end;
end;

function solve(x,y:longint):longint;
var r,sum,lc,rc,tem:longint;
begin
    r:=-1;sum:=0;
    while belong[x]<>belong[y] do
    begin
        query(1,pos[belong[x]],pos[x],lc,rc,tem);
                inc(sum,tem);
        if rc=r then dec(sum);
        r:=lc;
        x:=fa[belong[x]][0];
    end;
    query(1,pos[y],pos[x],lc,rc,tem);
        inc(sum,tem);
    if rc=r then dec(sum);
    exit(sum);
end;

procedure mend(x,y,z:longint);
begin
    while belong[x]<>belong[y] do
    begin
        insert(1,pos[belong[x]],pos[x],z);
        x:=fa[belong[x]][0];
    end;
    insert(1,pos[y],pos[x],z);
end;

begin
    readln(n,m);
    for i:=1 to n do read(v[i]);readln;
    j:=0;
    for i:=1 to n-1 do
    begin
        readln(x,y);
        add(x,y);
    end;
        deep[1]:=1;
    dfs1(1);
    cnt:=0;dfs2(1,1);
        build(1,1,n);
    for i:=1 to n do insert(1,pos[i],pos[i],v[i]);
        for i:=1 to m do
    begin
        read(ch);
        if ch=C then
        begin
            readln(x,y,z);
            t:=lca(x,y);
            mend(x,t,z);mend(y,t,z);
        end else
        begin
            readln(x,y);
                z:=lca(x,y);
                writeln(solve(x,z)+solve(y,z)-1);
        end;
    end;
end.

 

[BZOJ2243][SDOI2011]染色 解题报告|树链剖分

标签:

原文地址:http://www.cnblogs.com/mjy0724/p/4416168.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!