zoukankan      html  css  js  c++  java
  • 【NOI2015】软件包管理器

    P2106 - 【NOI2015】软件包管理器

    Description

    你决定设计你自己的软件包管理器。不可避免的,你要解决软件包之间的依赖关系。如果A依赖B,那么安装A之前需安装B,卸载B之前须卸载A。0号软件包不依赖任何软件包。依赖关系不存在环(包括自环)。
    你的任务是,求出每次安装、删除操作会改变多少个包的状态。
    安装一个已安装的软件包,或者卸载一个未安装的软件包,都不会改变任何软件包的安装状态,即在此情况下,改变安装状态的软件包数为0
    每次操作不仅需要计算安装软件包数,还作为操作影响后来的安装/删除

    Input

    第一行一个整数n,表示软件包的总数。
    随后n-1个整数a1,a2,...an-1,表示第i个软件包依赖第ai个软件包
    接下来一行一个整数q,表示询问数
    之后q行,每行一个询问,询问分为两种
    install x:表示安装x
    uninstall x:表示卸载x

    Output

    q行,每行一个整数,为第i步操作改变安装状态的软件包数

    Sample Input

    样例输入1:
    7
    0 0 0 1 1 5
    5
    install 5
    install 6
    uninstall 1
    install 4
    uninstall 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

    Sample Output

    样例输出1:
    3
    1
    3
    2
    3
    样例输出2:
    1
    3
    2
    1
    3
    1
    1
    1
    0
    1

    Hint

    样例输入1说明:

    Pic

    一开始所有的软件包都处于未安装状态。
    安装5号软件包,需安装0,1,5三个软件包
    之后安装6号软件包,只需安装6号软件包。此时安装了0,1,5,6四个软件包。
    卸载1号软件包需要卸载1,5,6三个软件包,此时只有0号软件包还处于安装状态
    之后安装4号软件包,需安装1,4两个软件包。此时0,1,4处于安装状态
    最后,卸载0号软件包会卸载所有的软件包

    数据提示:
    1,2:n=5000 q=5000
    3,4:n=100000 q=100000 没有卸载操作
    5,6,7,8 n=100000,q=100000 依赖关系和操作随机
    9-20 n=100000,q=100000 不随机

    先树链剖分,用线段树维护一下,线段树中初始值为1,表示这个软件包还没有安装。
    对于每个安装操作,查询这个点到根的权值和即可,并且要把查询的这一段都修改为0,表示已经安装。
    对于每个卸载操作,要查询以这个点为根的子树中有多少个点已经安装。
    这里需要在第二遍DFS的时候把回溯到这个点的
    dfn记录下来,
    因为某个点的
    dfn和回溯到这个点的dfn在线段树中对应的那个区间就刚好是以这个点为根的子树。
    这样就可以直接查询了。查询后把这个区间修改为1。
    关于lazy数组要注意一下,lazy[i]=0就代表这个点对应的区间都是安装了的,
    lazy[i]=1就代表这个点对应的区间都是没有安装的。
    所以
    lazy的初值不能赋为1也不能赋为0,在下放时,lazy[i]为初值时是不要下放的。
    这里卡了我蛮久。

      1 #include<set>
      2 #include<map>
      3 #include<queue>
      4 #include<stack>
      5 #include<ctime>
      6 #include<cmath>
      7 #include<string>
      8 #include<vector>
      9 #include<cstdio>
     10 #include<cstdlib>
     11 #include<cstring>
     12 #include<iostream>
     13 #include<algorithm>
     14 #define maxn 100010
     15 #define ls o*2
     16 #define rs o*2+1
     17 #define mi int mid=(l+r)>>1
     18 using namespace std;
     19 struct data{
     20   int nex,to;
     21 }e[maxn*2];
     22 int head[maxn],edge=0;
     23 int dfn1[maxn],dfn2[maxn],size[maxn],top[maxn],son[maxn],dad[maxn],deep[maxn],b[maxn*4],lazy[maxn*4];
     24 int size1[maxn*4],n;
     25 char s[12];
     26 void add(int from,int to){
     27   e[++edge].nex=head[from];
     28   e[edge].to=to;
     29   head[from]=edge;
     30 }
     31 void build(int o,int l,int r){
     32   size1[o]=r-l+1;
     33   if(l==r){b[o]=1;return;}
     34   mi;
     35   build(ls,l,mid);build(rs,mid+1,r);
     36   b[o]=b[ls]+b[rs];
     37 }
     38 void down(int o){
     39   if(lazy[o]==-1) return;
     40   b[ls]=size1[ls]*lazy[o];
     41   b[rs]=size1[rs]*lazy[o];
     42   lazy[ls]=lazy[o];lazy[rs]=lazy[o];
     43   lazy[o]=-1;
     44 }
     45 void dfs1(int x,int fa){
     46   size[x]++;
     47   for(int i=head[x];i;i=e[i].nex){
     48     int u=e[i].to;
     49     if(u==fa) continue;
     50     dad[u]=x;
     51     deep[u]=deep[x]+1;
     52     dfs1(u,x);
     53     size[x]+=size[u];
     54     if(size[son[x]]<size[u]) son[x]=u;
     55   }
     56 }
     57 int de=0;
     58 void dfs2(int x,int fa){
     59   ++de;
     60   dfn1[x]=de;
     61   if(son[x]) top[son[x]]=top[x],dfs2(son[x],x);
     62   for(int i=head[x];i;i=e[i].nex){
     63     int u=e[i].to;
     64     if(u==fa || u==son[x])continue;
     65     top[u]=u;
     66     dfs2(u,x);
     67   }
     68   dfn2[x]=de;
     69 }
     70 int find(int o,int l,int r,int u,int v){
     71   if(l!=r) down(o);
     72   if(l>=u && r<=v) return b[o];
     73   if(l>v || r<u) return 0;
     74   mi;
     75   if(v<=mid) return find(ls,l,mid,u,v);
     76   else if(u>mid) return find(rs,mid+1,r,u,v);
     77   else return find(ls,l,mid,u,mid)+find(rs,mid+1,r,mid+1,v);
     78 }
     79 void change(int o,int l,int r,int u,int v,int w){
     80   if(l!=r) down(o);
     81   if(l>=u && r<=v){
     82     b[o]=w*size1[o];
     83     lazy[o]=w;
     84     return;
     85   }
     86   if(l>v || r<u) return;
     87   mi;
     88   if(v<=mid) change(ls,l,mid,u,v,w);
     89   else if(u>mid) change(rs,mid+1,r,u,v,w);
     90   else change(ls,l,mid,u,mid,w),change(rs,mid+1,r,mid+1,v,w);
     91   b[o]=b[ls]+b[rs];
     92 }
     93 void lca(int x,int y){
     94   int sum=0;
     95   while(top[x]!=top[y]){
     96     if(deep[top[x]]>deep[top[y]]) sum+=find(1,1,n,dfn1[top[x]],dfn1[x]),
     97                     change(1,1,n,dfn1[top[x]],dfn1[x],0),x=dad[top[x]];
     98     else sum+=find(1,1,n,dfn1[top[y]],dfn1[y]),change(1,1,n,dfn1[top[y]],dfn1[y],0),y=dad[top[y]];
     99   }
    100   if(deep[x]>deep[y]) swap(x,y);
    101   sum+=find(1,1,n,dfn1[x],dfn1[y]);change(1,1,n,dfn1[x],dfn1[y],0);
    102   printf("%d
    ",sum);
    103 }
    104 int main()
    105 {
    106   freopen("!.in","r",stdin);
    107   freopen("!.out","w",stdout);
    108   int x;
    109   scanf("%d",&n);
    110   for(int i=2;i<=n;i++)
    111     scanf("%d",&x),add(x+1,i),add(i,x+1);
    112   for(int i=0;i<=4*n;i++) lazy[i]=-1;
    113   top[1]=1,dad[1]=1;
    114   dfs1(1,0);dfs2(1,0);build(1,1,n);
    115   int qes;scanf("%d",&qes);
    116   for(int i=1;i<=qes;i++){
    117     scanf("%s%d",s,&x);
    118     x++;
    119     if(s[0]=='i') lca(1,x);
    120     if(s[0]=='u'){
    121       printf("%d
    ",size[x]-find(1,1,n,dfn1[x],dfn2[x]));
    122       change(1,1,n,dfn1[x],dfn2[x],1);
    123     }
    124   }
    125 }
    
    
    
     
  • 相关阅读:
    maven 阿里镜像
    红黑树数据结构剖析
    一个简单的通用Makefile实现
    如何取消开机硬盘自检
    用友u8采购发票如何取消审核
    应付帐款—制单处理,出现“供应商被锁定”的解决方法
    用友系统管理员密码清除
    用友软件系统管理员账号admin密码忘记了,如何解决?
    用友 提示“尚有已全部暂估报销的单据未进行处理,不能进行12月的期末处理!”
    MySQL Windows版安装详解
  • 原文地址:https://www.cnblogs.com/pantakill/p/6622335.html
Copyright © 2011-2022 走看看