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=100000q=100000 树链剖分算是一个比较基础的板子题。再加上线段树区间更新lazy标记。
对于卸载一个软件来说,我们需要把它的子树全部卸载掉。
对于安装一个软件来说,我们需要安装从这个节点到它的头节点所有的软件。这样我们用线段树区间求和后,再用深度差减去这个线段树区间求和的值就好了。这个题比较坑,wa了好几次。洛谷上一直re,在vj上过了。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<string>
#include<vector>
#include<queue>
#define ll long long
using namespace std;const int maxx=2e5+100;
int head[maxx],top[maxx];
int fa[maxx],son[maxx],dep[maxx];
int id[maxx],pre[maxx],size[maxx];
int n,m,tot,sign;
struct edge{int to;int next;
}e[maxx*4];
struct node{int l;int r;int v;int lazy;
}p[maxx*4];
/*------------准备阶段-----------*/
int inn()
{  char ch;  int a=0;  while((ch=getchar())==' '||ch=='\n');  a+=ch-'0';  while((ch=getchar())!=' '&&ch!='\n')  {  a*=10;  a+=ch-'0';  }  return a;
}
void init()
{memset(dep,0,sizeof(dep));memset(size,0,sizeof(size));memset(head,-1,sizeof(head));tot=sign=0;
}
void addedge(int u,int v)
{e[tot].to=v; e[tot].next=head[u];head[u]=tot++;
}
/*------------dfs----------*/
void dfs1(int u,int f)
{size[u]=1;dep[u]=dep[fa[u]]+1;for(int i=head[u];i!=-1;i=e[i].next){int to=e[i].to;if(to==f) continue;fa[to]=u;dfs1(to,u);size[u]+=size[to];if(size[to]>size[son[u]]) son[u]=to;}
}
void dfs2(int u,int Top)
{top[u]=Top;id[u]=++sign;pre[sign]=u;if(son[u]) dfs2(son[u],Top);for(int i=head[u];i!=-1;i=e[i].next){int to=e[i].to;if(to==fa[u]||to==son[u]) continue;dfs2(to,to);}
}
/*--------------------线段树-----------------*/
void pushup(int cur)
{p[cur].v=(p[2*cur+1].v+p[2*cur].v);
}
void pushdown(int cur)
{p[2*cur].lazy=p[cur].lazy;p[2*cur+1].lazy=p[cur].lazy;p[2*cur].v=(p[cur].lazy*(p[2*cur].r-p[2*cur].l+1));p[2*cur+1].v=(p[cur].lazy*(p[2*cur+1].r-p[2*cur+1].l+1));p[cur].lazy=-1;
}
void build(int l,int r,int cur)
{p[cur].l=l;p[cur].r=r;p[cur].v=0;p[cur].lazy=-1;if(l==r){return ;}int mid=(l+r)/2;build(l,mid,2*cur);build(mid+1,r,2*cur+1);pushup(cur);
}
void update(int l,int r,int cur,int add)
{int L=p[cur].l;int R=p[cur].r;if(l<=L&&R<=r){p[cur].v=(p[cur].r-p[cur].l+1)*add;p[cur].lazy=add;return ; }if(p[cur].lazy!=-1)pushdown(cur);int mid=(L+R)/2;if(r<=mid) update(l,r,2*cur,add);else if(l>mid) update(l,r,2*cur+1,add);else{update(l,mid,2*cur,add);update(mid+1,r,2*cur+1,add);}pushup(cur);
}
int query(int l,int r,int cur)
{int L=p[cur].l;int R=p[cur].r;if(l<=L&&R<=r){return p[cur].v;}if(p[cur].lazy!=-1)pushdown(cur);int mid=(L+R)/2;if(r<=mid) return query(l,r,2*cur);else if(l>mid) return query(l,r,2*cur+1);else return query(l,mid,2*cur)+query(mid+1,r,2*cur+1);
}
/*-------------树链剖分------------*/
void Update(int x,int y,int z)
{while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);update(id[top[x]],id[x],1,z);x=fa[top[x]];}if(id[x]>id[y]) swap(x,y);update(id[x],id[y],1,z);
}
int Query(int x,int y)
{int ans=0;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);ans+=(query(id[top[x]],id[x],1));x=fa[top[x]];}if(id[x]>id[y]) swap(x,y);ans+=query(id[x],id[y],1);return ans;
}
int main()
{while(scanf("%d",&n)!=EOF){init();int x;for(int i=2;i<=n;i++){x=inn();x++;addedge(x,i);addedge(i,x);}dfs1(1,0);dfs2(1,1);build(1,n,1);char s[10];m=inn(); while(m--){scanf("%s",s);x=inn();x++;if(s[0]=='i'){printf("%d\n",dep[x]-dep[1]-Query(1,x)+1);Update(1,x,1);}else if(s[0]=='u'){printf("%d\n",query(id[x],id[x]+size[x]-1,1));update(id[x],id[x]+size[x]-1,1,0);}}}return 0;
}


树链剖分第二题,加油。
努力加油a啊

软件包管理器(树链剖分)相关推荐

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

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

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

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

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

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

  4. BZOJ - 4196 软件包管理器 (树链剖分+dfs序+线段树)

    题目链接 设白色结点为未安装的软件,黑色结点为已安装的软件,则: 安装软件i:输出结点i到根的路径上的白色结点的数量,并把结点i到根的路径染成黑色.复杂度$O(nlog^2n)$ 卸载软件i:输出结点 ...

  5. 树链剖分概念及模板 + 例题 [POJ3237 tree + 软件包管理器]

    文章目录 概念 模板 例题1:软件包管理器 题目 题解 代码实现 例题2:POJ3237 tree 题目 题解 代码实现 概念 树链剖分主要是用于解决以下这两个问题. 1.更改树上点x到点y的最短路径 ...

  6. 【树链剖分】软件管理(luogu 2146/金牌导航 树链剖分-2)

    正题 luogu 2146 金牌导航 树链剖分-2 题目大意 有若干软件,除了软件0,所有软件都依赖且只依赖于另外一个软件 当要删除一个软件时,所有依赖于该软件的软件都要删掉 当安装一个软件时,该软件 ...

  7. bzoj4196:[Noi2015]软件包管理器

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

  8. [NOI2015]软件包管理器

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

  9. 树链剖分 讲解+模板+习题

    今天我们来讲一下树链剖分 树链剖分是什么? 树链剖分是一种用来维护树上路径信息的在线方法,可以处理在线. 通常通过一种方法,将一棵树剖分成若干条链,然后通过数据结构(线段树,BIT等)去维护. 我们通 ...

最新文章

  1. Java实现文件的预览
  2. Maven实战(三)Eclipse构建Maven项目
  3. er图主码外码怎么看_霸屏了!因为这个老师,广科er纷纷表示要转专业了
  4. 【Luogu】P1383高级打字机
  5. 通过google app engine 在google cloud 部署支持quic的Java web 应用(多种方式)
  6. TensorFlow学习笔记(五)Session的2种用法
  7. MYSQL模式匹配:REGEXP和like用法
  8. 《天天数学》连载04:一月四日
  9. 开机时无法进入系统,提示windows system32/winload.exe 无法加载
  10. RUI手机桌面,开年大更新绝对值得拥有!
  11. Tar的详细用法(转自Linux伊甸园)
  12. AT89C51中断模板(宏定义)
  13. 工作一年的收获与思考
  14. 运算放大器 你想知道的都在这里
  15. 计算机毕业设计之全网独家Spark租房爬虫数据分析与推荐系统 租房大数据 租房app 租房数据分析 租房爬虫 房源推荐系统 房源数据分析 房源可视化
  16. 利用CASS使用三种方法计算两期土方
  17. Qt下 汉字转换拼音
  18. 【docker 安装-环境初始化】
  19. cad2006激活未找到html文件,解决cad提示“cad加载自定义文件失败 未找到acad”的方法...
  20. 转型AI ,80后华为Java工程师的故事

热门文章

  1. IOS中的swift和oc关于对象模型的description方法重写
  2. 驱动人生2008_驱动人生致敬深圳经济特区建立四十周年!
  3. 广联达2018模板算量步骤_广联达GTJ2021操作教程:造价小白3天速成,计量效率翻倍...
  4. keil单片机C语言输入函数,keil编写C程序是不是不能在函数内定义变量啊,求大神...
  5. 根据数据库表gengxin实体类_ASP.NET开发实战——(十二)数据库之EF Migrations
  6. Android开发之Gradle多渠道打包总结
  7. macrotask和microtask以及EventLoop的介绍
  8. springboot之websocket
  9. 谨记2017年8月30日10:03:26
  10. 浪潮I9000革新传统刀片 解决基础架构统一难题