zoukankan      html  css  js  c++  java
  • bzoj4196[Noi2015]软件包管理器

    Description

     Linux用户和OSX用户一定对软件包管理器不会陌生。通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置。Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是优秀的软件包管理器。

    你决定设计你自己的软件包管理器。不可避免地,你要解决软件包之间的依赖问题。如果软件包A依赖软件包B,那么安装软件包A以前,必须先安装软件包B。同时,如果想要卸载软件包B,则必须卸载软件包A。现在你已经获得了所有的软件包之间的依赖关系。而且,由于你之前的工作,除0号软件包以外,在你的管理器当中的软件包都会依赖一个且仅一个软件包,而0号软件包不依赖任何一个软件包。依赖关系不存在环(若有m(m≥2)个软件包A1,A2,A3,…,Am,其中A1依赖A2,A2依赖A3,A3依赖A4,……,Am−1依赖Am,而Am依赖A1,则称这m个软件包的依赖关系构成环),当然也不会有一个软件包依赖自己。
    现在你要为你的软件包管理器写一个依赖解决程序。根据反馈,用户希望在安装和卸载某个软件包时,快速地知道这个操作实际上会改变多少个软件包的安装状态(即安装操作会安装多少个未安装的软件包,或卸载操作会卸载多少个已安装的软件包),你的任务就是实现这个部分。注意,安装一个已安装的软件包,或卸载一个未安装的软件包,都不会改变任何软件包的安装状态,即在此情况下,改变安装状态的软件包数为0。
     

    Input

    输入文件的第1行包含1个正整数n,表示软件包的总数。软件包从0开始编号。

    随后一行包含n−1个整数,相邻整数之间用单个空格隔开,分别表示1,2,3,…,n−2,n−1号软件包依赖的软件包的编号。
    接下来一行包含1个正整数q,表示询问的总数。
    之后q行,每行1个询问。询问分为两种:
    installx:表示安装软件包x
    uninstallx:表示卸载软件包x
    你需要维护每个软件包的安装状态,一开始所有的软件包都处于未安装状态。对于每个操作,你需要输出这步操作会改变多少个软件包的安装状态,随后应用这个操作(即改变你维护的安装状态)。
     

    Output

    输出文件包括q行。

    输出文件的第i行输出1个整数,为第i步操作中改变安装状态的软件包数。
     

    Sample Input

    7
    0 0 0 1 1 5
    5
    install 5
    install 6
    uninstall 1
    install 4
    uninstall 0

    Sample Output

    3
    1
    3
    2
    3

    HINT

     

     一开始所有的软件包都处于未安装状态。

    安装 5 号软件包,需要安装 0,1,5 三个软件包。

    之后安装 6 号软件包,只需要安装 6 号软件包。此时安装了 0,1,5,6 四个软件包。

    卸载 1 号软件包需要卸载 1,5,6 三个软件包。此时只有 0 号软件包还处于安装状态。

    之后安装 4 号软件包,需要安装 1,4 两个软件包。此时 0,1,4 处在安装状态。

    最后,卸载 0 号软件包会卸载所有的软件包。

     

    输入样例#2:
    10
    0 1 2 1 3 0 0 3 2
    10
    install 0
    install 3
    uninstall 2
    install 7
    install 5
    install 9
    uninstall 9
    install 4
    install 1
    install 9
    输出样例#2:
    1
    3
    2
    1
    3
    1
    1
    1
    0
    1


    【数据范围】

    【时限1s,内存512M】

     
     
    题解
    裸的树链剖分,曾经写过dfs的,新学一种只要bfs的树链剖分,不怕栈溢出。
     
     
    代码
      1 program rrr(input,output);
      2 type
      3   etype=record
      4      t,next:longint;
      5    end;
      6    treetype=record
      7      l,r,s,d:longint;
      8    end;
      9 var
     10   e:array[0..200020]of etype;
     11   head,father,dep,top,siz,son,sson,oot,idx,q:array[-3..100010]of longint;
     12   a:array[0..400040]of treetype;
     13   n,qq,i,j,cnt,ans,h,t,x:longint;
     14   s:string;
     15 procedure add(x,y:longint);
     16 begin
     17    inc(cnt);e[cnt].t:=y;e[cnt].next:=head[x];head[x]:=cnt;
     18 end;
     19 procedure prepare;
     20 begin
     21    h:=0;t:=1;q[1]:=0;dep[0]:=1;
     22    while h<t do
     23       begin
     24          inc(h);
     25          i:=head[q[h]];
     26          while i<>0 do
     27             begin
     28                dep[e[i].t]:=dep[q[h]]+1;
     29                inc(t);q[t]:=e[i].t;
     30                i:=e[i].next;
     31             end;
     32       end;
     33    for i:=0 to n-1 do siz[i]:=1;
     34    fillchar(sson,sizeof(sson),0);
     35    for i:=0 to n-1 do son[i]:=-1;
     36    for i:=n downto 2 do
     37       begin
     38          inc(siz[father[q[i]]],siz[q[i]]);
     39          if siz[q[i]]>sson[father[q[i]]] then begin son[father[q[i]]]:=q[i];sson[father[q[i]]]:=siz[q[i]]; end;
     40       end;
     41    fillchar(idx,sizeof(idx),0);father[0]:=-1;oot[-1]:=0;
     42    for i:=1 to n do
     43       if idx[q[i]]=0 then
     44          begin
     45             cnt:=oot[father[q[i]]];j:=q[i];
     46             while j<>-1 do
     47                begin
     48                   top[j]:=q[i];
     49                   inc(cnt);idx[j]:=cnt;oot[j]:=cnt;
     50                   inc(oot[father[j]],siz[j]);
     51                   j:=son[j];
     52                end;
     53          end;
     54 end;
     55 procedure build(k,l,r:longint);
     56 var
     57   mid:longint;
     58 begin
     59    a[k].l:=l;a[k].r:=r;a[k].d:=-1;a[k].s:=0;
     60    if l=r then exit;
     61    mid:=(l+r)>>1;
     62    build(k+k,l,mid);
     63    build(k+k+1,mid+1,r);
     64 end;
     65 procedure pushdown(k:longint);
     66 var
     67   i:longint;
     68 begin
     69    if a[k].l=a[k].r then begin a[k].d:=-1;exit; end;
     70    i:=k+k;
     71    if a[k].d=0 then begin a[i].s:=0;a[i].d:=0;a[i+1].s:=0;a[i+1].d:=0; end
     72    else begin a[i].s:=a[i].r-a[i].l+1;a[i].d:=1;a[i+1].s:=a[i+1].r-a[i+1].l+1;a[i+1].d:=1; end;
     73    a[k].d:=-1;
     74 end;
     75 function ask(k,x,y:longint):longint;
     76 var
     77   mid,ans:longint;
     78 begin
     79    if a[k].d<>-1 then pushdown(k);
     80    if (x<=a[k].l) and (a[k].r<=y) then exit(a[k].s);
     81    ans:=0;mid:=(a[k].l+a[k].r)>>1;
     82    if x<=mid then ans:=ask(k+k,x,y);
     83    if mid<y then ans:=ans+ask(k+k+1,x,y);
     84    exit(ans);
     85 end;
     86 procedure change0(k,x,y:longint);
     87 var
     88   mid,i:longint;
     89 begin
     90    if a[k].d<>-1 then pushdown(k);
     91    if (x<=a[k].l) and (a[k].r<=y) then begin a[k].s:=0;a[k].d:=0;exit;end;
     92    mid:=(a[k].l+a[k].r)>>1;i:=k+k;
     93    if x<=mid then change0(i,x,y);
     94    if mid<y then change0(i+1,x,y);
     95    a[k].s:=a[i].s+a[i+1].s;
     96 end;
     97 procedure change1(k,x,y:longint);
     98 var
     99   mid,i:longint;
    100 begin
    101    if a[k].d<>-1 then pushdown(k);
    102    if (x<=a[k].l) and (a[k].r<=y) then begin a[k].s:=a[k].r-a[k].l+1;a[k].d:=1;exit;end;
    103    mid:=(a[k].l+a[k].r)>>1;i:=k+k;
    104    if x<=mid then change1(i,x,y);
    105    if mid<y then change1(i+1,x,y);
    106    a[k].s:=a[i].s+a[i+1].s;
    107 end;
    108 procedure install;
    109 begin
    110    ans:=dep[x];
    111    while x<>-1 do begin ans:=ans-ask(1,idx[top[x]],idx[x]);change1(1,idx[top[x]],idx[x]);x:=father[top[x]]; end;
    112    writeln(ans);
    113 end;
    114 procedure uninstall;
    115 begin
    116    writeln(ask(1,idx[x],idx[x]+siz[x]-1));
    117    change0(1,idx[x],idx[x]+siz[x]-1);
    118 end;
    119 begin
    120    assign(input,'manager.in');assign(output,'manager.out');reset(input);rewrite(output);
    121    readln(n);
    122    fillchar(head,sizeof(head),0);cnt:=0;
    123    for i:=1 to n-1 do begin read(father[i]);add(father[i],i); end;
    124    prepare;
    125    build(1,1,n);
    126    readln(qq);
    127    for i:=1 to qq do
    128       begin
    129          readln(s);
    130          if s[1]='i' then begin delete(s,1,8);val(s,x);install; end
    131          else begin delete(s,1,10);val(s,x);uninstall; end;
    132       end;
    133    close(input);close(output);
    134 end.

    吐槽:不知道为什么,这个树剖和以前的dfs树剖,在uoj、洛谷、codevs都过了,但在bzoj都过不了,而且上面程序我用cena测了官方数据(dfs的树剖cena测会爆栈),也过了。

  • 相关阅读:
    括号序列
    单向TSP
    Black Box
    震惊!!!某初中生竟30min一蓝两紫一黑!!!
    荷马史诗
    SUFEQPRE
    UVA劲歌金曲
    UVA城市里的间谍
    饼图----插件
    折线图-----插件
  • 原文地址:https://www.cnblogs.com/Currier/p/6535312.html
Copyright © 2011-2022 走看看