[BZOJ4196] [Noi2015]软件包管理器

传送门

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

题目大意

支持
1.树链修改+查询
2.子树修改+查询

题解

树链剖分包含DFS序

const
    maxn=100010;
var
    w:array[0..3*maxn,1..2]of longint;
    seg:array[0..8*maxn,1..4]of longint;
    pos,top,fa,son,size,dep:array[0..maxn]of longint;
    x:array[0..maxn,1..2]of longint;
    i,j,k:longint;
    n,m,len,a,t1,t2:longint;
    cha,ch:char;
procedure swap(var a,b:longint);
var tt:longint;
begin tt:=a; a:=b; b:=tt; 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]:=-1;
    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]:=-1; exit; end;
    if seg[a,4]=1
    then 
        begin
            seg[a<<1,3]:=seg[a<<1,2]-seg[a<<1,1]+1; seg[a<<1,4]:=1;
            seg[a<<1+1,3]:=seg[a<<1+1,2]-seg[a<<1+1,1]+1; seg[a<<1+1,4]:=1;
        end
    else
        begin
            seg[a<<1,3]:=0; seg[a<<1,4]:=0;
            seg[a<<1+1,3]:=0; seg[a<<1+1,4]:=0;
        end;
    seg[a,4]:=-1;
end;
procedure update(a,l,r,b:longint);
var mid:longint;
begin
    if seg[a,4]<>-1 then pushdown(a);
    if (seg[a,1]=l)and(seg[a,2]=r)
    then begin if b=1 then seg[a,3]:=r-l+1 else seg[a,3]:=0; seg[a,4]:=b; exit; end;
    mid:=(seg[a,1]+seg[a,2])>>1;
    if r<=mid then update(a<<1,l,r,b) else
    if l>mid then update(a<<1+1,l,r,b)
    else begin update(a<<1,l,mid,b); update(a<<1+1,mid+1,r,b); 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]<>-1 then pushdown(a);
    if (seg[a,1]=l)and(seg[a,2]=r) 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 dfs1(a:longint); {fa,son,size,dep}
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]; top[a]:=pre; inc(len); pos[a]:=len; x[a,1]:=len;
    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;    
    x[a,2]:=len;
end;
function queryans(a,b:longint):longint;
var ans:longint;
begin
    ans:=0;
    while top[a]<>top[b] do
        begin
            if dep[top[a]]<dep[top[b]] then swap(a,b);
            inc(ans,query(1,pos[top[a]],pos[a]));
            update(1,pos[top[a]],pos[a],1);
            a:=fa[top[a]];
        end;
    if dep[a]>dep[b] then swap(a,b);
    inc(ans,query(1,pos[a],pos[b]));
    update(1,pos[a],pos[b],1);
    exit(ans);
end;
begin
    readln(n); len:=n+1;
    for i:=2 to n do
        begin
            read(a); inc(a);
            init(a,i); init(i,a);
        end;
    dep[1]:=1; fa[1]:=0; size[0]:=0;
    dfs1(1);
    build(1,1,n); len:=0;
    dfs2(1,1);
    readln(m);
    for i:=1 to m do
        begin
            read(cha);
            if cha='i'
            then begin readln(ch,ch,ch,ch,ch,ch,a); inc(a); writeln(dep[a]-queryans(1,a)); end
            else begin readln(ch,ch,ch,ch,ch,ch,ch,ch,a); inc(a); writeln(query(1,x[a,1],x[a,2])); update(1,x[a,1],x[a,2],0); end;
        end;
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值