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 号软件包会卸载所有的软件包。
n=100000
q=100000
题解:
其实也是一道树链剖分模板题
线段树维护状态
安装软件包时查询从当前点到根节点已安装的软件包数,用深度减一下就得到答案。
查询过后立即进行修改
卸载软件包时查询自己以及自己子节点中已安装的软件包数(这些点在线段树中编号连续)
同样查询过后立即修改
写的时候真是小错不断,实在无语……orz
线段树差点写挂……
注意:在进行安装软件包操作时每一次查询后都要有修改,不要漏了
代码:

  1 #include<cstdio>
  2 #include<iostream>
  3 using namespace std;
  4
  5 const int MAXN=100005;
  6 struct node
  7 {
  8     int v;
  9     node *next;
 10 }pool[MAXN],*h[MAXN];
 11 int cnt,tot;
 12 int fa[MAXN],dep[MAXN],size[MAXN],son[MAXN];
 13 int top[MAXN],rk[MAXN];
 14
 15 void addedge(int u,int v)
 16 {
 17     node *p=&pool[++cnt];
 18     p->v=v;p->next=h[u];h[u]=p;
 19 }
 20 void dfs1(int u)
 21 {
 22     int v;
 23     size[u]=1;
 24     int Bson=0,sonnum=-1;
 25     for(node *p=h[u];p;p=p->next)
 26         if(fa[u]!=(v=p->v))
 27         {
 28             fa[v]=u;
 29             dep[v]=dep[u]+1;
 30             dfs1(v);
 31             size[u]+=size[v];
 32             if(size[v]>Bson) Bson=size[v],sonnum=v;
 33         }
 34     son[u]=sonnum;
 35 }
 36 void dfs2(int u)
 37 {
 38     int v=son[u];
 39     if(v!=-1)
 40     {
 41         top[v]=top[u];
 42         rk[v]=++tot;
 43         dfs2(v);
 44     }
 45     for(node *p=h[u];p;p=p->next)
 46         if(fa[v=p->v]==u && v!=son[u])
 47         {
 48             top[v]=v;
 49             rk[v]=++tot;
 50             dfs2(v);
 51         }
 52 }
 53
 54 struct tree
 55 {
 56     int l,r,lazy,sum;
 57     tree *left,*right;
 58 }t[3*MAXN],*root;
 59 int cnt1;
 60 void update(tree *p)
 61 {
 62     p->sum=0;
 63     if(p->left) p->sum+=p->left->sum;
 64     if(p->right) p->sum+=p->right->sum;
 65 }
 66 void pushdown(tree *p)
 67 {
 68     if(p->lazy!=-1)
 69     {
 70         p->sum=p->lazy*(p->r-p->l+1);
 71         if(p->left) p->left->lazy=p->lazy,p->left->sum=p->lazy*(p->left->r-p->left->l+1);
 72         if(p->right) p->right->lazy=p->lazy,p->right->sum=p->lazy*(p->right->r-p->right->l+1);
 73         p->lazy=-1;
 74     }
 75 }
 76 void Build_Tree(tree *p,int l,int r)
 77 {
 78     p->l=l;p->r=r;p->lazy=-1;
 79     if(l==r) return;
 80     p->left=&t[++cnt1];p->right=&t[++cnt1];
 81     int mid=(l+r)/2;
 82     Build_Tree(p->left,l,mid);
 83     Build_Tree(p->right,mid+1,r);
 84 }
 85 void change(tree *p,int l,int r,int c)
 86 {
 87     if(p->l==l && p->r==r)
 88     {
 89         p->lazy=c;
 90         p->sum=p->lazy*(p->r-p->l+1);
 91         return;
 92     }
 93     pushdown(p);
 94     if(p->left->r>=r) change(p->left,l,r,c);
 95     else if(p->right->l<=l) change(p->right,l,r,c);
 96     else change(p->left,l,p->left->r,c),change(p->right,p->right->l,r,c);
 97     update(p);
 98 }
 99 int query(tree *p,int l,int r)
100 {
101     if(p->l==l && p->r==r)
102     {
103         if(p->lazy!=-1) p->sum=p->lazy*(p->r-p->l+1);
104         return p->sum;
105     }
106     pushdown(p);
107     if(p->left->r>=r) return query(p->left,l,r);
108     else if(p->right->l<=l) return query(p->right,l,r);
109     else return query(p->left,l,p->left->r)+query(p->right,p->right->l,r);
110 }
111
112 int Sum(int x,int y)
113 {
114     int ret=0;
115     int f1=top[x],f2=top[y];
116     while(f1!=f2)
117     {
118         if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
119         ret+=query(root,rk[f1],rk[x]);
120         change(root,rk[f1],rk[x],1);
121         x=fa[f1];f1=top[x];
122     }
123     if(dep[x]>dep[y]) swap(x,y);
124     ret+=query(root,rk[x],rk[y]);
125     change(root,rk[x],rk[y],1);/**/
126     return ret;
127 }
128
129 int main()
130 {
131     int n,i,a,q;
132     char ch[11];
133     scanf("%d",&n);
134     for(i=1;i<n;i++)
135         scanf("%d",&a),addedge(a,i);
136
137     dfs1(0);
138     top[0]=0;rk[0]=++tot;
139     dfs2(0);
140     root=&t[++cnt1];
141     Build_Tree(root,1,n);
142
143     scanf("%d",&q);
144     while(q --> 0)
145     {
146         scanf("%s%d",ch,&a);
147         if(ch[0]=='i')
148             printf("%d\n",dep[a]+1-Sum(a,0));
149         else
150         {
151             printf("%d\n",query(root,rk[a],rk[a]+size[a]-1));
152             change(root,rk[a],rk[a]+size[a]-1,0);
153         }
154     }
155
156     return 0;
157 }

View Code

转载于:https://www.cnblogs.com/lindalee/p/7258791.html

bzoj4196:[Noi2015]软件包管理器相关推荐

  1. BZOJ4196[Noi2015]软件包管理器——树链剖分+线段树

    题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个 ...

  2. BZOJ4196: [Noi2015]软件包管理器 (好题

    好题啊,做到这题想起以前靠线段树维护子树的时候 那时候没见过链操作,搞不清树剖有什么用 这题就结合了子树操作和树链操作,也是把dfs序的in out完整用上了 树剖exp++ #include< ...

  3. [Bzoj4196] [NOI2015] 软件包管理器 [树链剖分,线段树]

    题解摘要:树链剖分后用线段树区间查询修改,对于安装软件,将改点到根的路径全部变为1,对于卸载软件,将子树清空.注意边界,编号是从0开始的,容易漏掉树根. 第一次写树剖- 1 #include < ...

  4. [NOI2015]软件包管理器

    4621 [NOI2015]软件包管理器  题目等级 : 钻石 Diamond 题目描述 Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行 ...

  5. P2146 [NOI2015] 软件包管理器

    P2146 [NOI2015] 软件包管理器 题意: 如果软件包 a 依赖软件包 b,那么安装软件包 a 以前,必须先安装软件包 b.同时,如果想要卸载软件包 b,则必须卸载软件包 a. 软件包之间存 ...

  6. 洛谷P2146DTOJ2409 [NOI2015]软件包管理器

    洛谷P2146&&DTOJ2409 [NOI2015]软件包管理器 题目 题目描述 输入格式 输出格式 样例 样例输入1 样例输出1 样例输入2 样例输出2 数据范围与提示 样例1说明 ...

  7. BZOJ4196:[NOI2015]软件包管理器——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=4196 https://www.luogu.org/problemnew/show/P2146 你决定 ...

  8. NOI2015 Day1 T2 软件包管理器 树链剖分

    NKOJ3423 NOI2015 软件包管理器 时间限制 : 20000 MS 空间限制 : 524288 KB 问题描述 Linux用户和OS X用户一定对软件包管理器不会陌生.通过软件包管理器,你 ...

  9. 【NOI2015】软件包管理器

    NOI难得的水题,话说还是T2诶--又学到了线段树的一种新的魔性使用 看sxysxy大神的代码才写出来的,sxysxy_orz 原题: Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包 ...

最新文章

  1. 本周学习进度表及时间安排(2018-1-7~2018-1-13)
  2. 【数据挖掘】K-Means 二维数据聚类分析 ( K-Means 迭代总结 | K-Means 初始中心点选择方案 | K-Means 算法优缺点 | K-Means 算法变种 )
  3. qq推广 qq在线客服工具
  4. 设计模式总结一波点点
  5. Qt工作笔记-Qt creator如何生成dll,以及如何移植到vs上
  6. Linux——好用的一些命令(一)(保持更新)
  7. java初反射_java中的反射机制
  8. Python for Infomatics 第12章 网络编程四(译)
  9. vlc_for_android(基于git-3.0.0)快速集成并播放电视节目直播
  10. 跟着鬼哥学so修改,五,实例第二篇
  11. 12项目管理--项目采购管理
  12. 内存颗粒位宽和容量_内存颗粒的位数是指什么?
  13. 【软件工具】之 TotalCommander
  14. Vue使用插件v-viewer预览单张图片
  15. python爬取双色球历史数据_爬取双色球历史数据
  16. 钉钉自定义机器人python_钉钉自定义机器人demo
  17. 简要了解ios机型,推出年份,型号,容量,显示屏大小以及iOS系统
  18. 绿巨能 macbook pro 电池
  19. 基于51单片机来开发的智能感应开盖垃圾桶
  20. Java基础之Java数据类型

热门文章

  1. shell脚本安装mysql并安装一个小服务
  2. 九种破解Xp登录密码方法
  3. 彩信的基本原理(转贴)
  4. 美团点评效果广告实验配置平台的设计与实现
  5. 厉害了,Spring Cloud Alibaba 发布 GA 版本!
  6. Redis 缓存和 MySQL 数据如何实现一致性?
  7. 大话程序猿眼里最全的高并发,快收藏!
  8. 程序员的创业陷阱:接私活
  9. Spring Boot 2.0 新特性和发展方向
  10. Android 面试 - 动画