BZOJ4196:[NOI2015]软件包管理器——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=4196
https://www.luogu.org/problemnew/show/P2146
你决定设计你自己的软件包管理器。不可避免地,你要解决软件包之间的依赖问题。如果软件包A依赖软件包B,那么安装软件包A以前,必须先安装软件包B。同时,如果想要卸载软件包B,则必须卸载软件包A。现在你已经获得了所有的软件包之间的依赖关系。而且,由于你之前的工作,除0号软件包以外,在你的管理器当中的软件包都会依赖一个且仅一个软件包,而0号软件包不依赖任何一个软件包。依赖关系不存在环(若有m(m≥2)个软件包A1,A2,A3,⋯,Am,其中A1依赖A2,A2依赖A3,A3依赖A4,……,A[m-1]依赖Am,而Am依赖A1,则称这m个软件包的依赖关系构成环),当然也不会有一个软件包依赖自己。
现在你要为你的软件包管理器写一个依赖解决程序。根据反馈,用户希望在安装和卸载某个软件包时,快速地知道这个操作实际上会改变多少个软件包的安装状态(即安装操作会安装多少个未安装的软件包,或卸载操作会卸载多少个已安装的软件包),你的任务就是实现这个部分。注意,安装一个已安装的软件包,或卸载一个未安装的软件包,都不会改变任何软件包的安装状态,即在此情况下,改变安装状态的软件包数为0。
题面很长,耐心看完就知道这是道树剖的板子题。
(然而不会求子树和的我还是去看了题解)
我们把安装的权值为1,未安装为0。
对于下载操作只需要查询该点到根节点的路程-1的个数。
对于卸载操作只需要查询该点的子树的1的个数。
(当然别忘了二者的修改。)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N=2e5+;
const int INF=;
inline int read(){
int X=,w=;char ch=;
while(ch<''||ch>''){w|=ch=='-';ch=getchar();}
while(ch>=''&&ch<='')X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct node{
int to,nxt;
}edge[*N];
struct tree{
int lazy,sum;
}t[*N];
int head[N],cnt,tot,n;
inline void add(int u,int v){
edge[++cnt].to=v;edge[cnt].nxt=head[u];head[u]=cnt;
}
int fa[N],dep[N],size[N],son[N],top[N],pos[N],idx[N];
void dfs1(int u){
size[u]=;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==fa[u])continue;
fa[v]=u;dep[v]=dep[u]+;
dfs1(v);
size[u]+=size[v];
if(!son[u]||size[v]>size[son[u]])son[u]=v;
}
return;
}
void dfs2(int u,int anc){
tot++;
pos[u]=tot;
idx[tot]=u;
top[u]=anc;
if(!son[u])return;
dfs2(son[u],anc);
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
return;
}
inline void pushdown(int a,int l,int r){
int mid=(l+r)>>;
if(t[a].lazy!=-){
t[a*].lazy=t[a*+].lazy=t[a].lazy;
t[a*].sum=t[a].lazy*(mid-l+);
t[a*+].sum=t[a].lazy*(r-mid);
t[a].lazy=-;
}
return;
}
void modify(int a,int l,int r,int l1,int r1,int v){
if(r1<l||r<l1)return;
if(l1<=l&&r<=r1){
t[a].sum=v*(r-l+);
t[a].lazy=v;
return;
}
int mid=(l+r)>>;
pushdown(a,l,r);
modify(a*,l,mid,l1,r1,v);
modify(a*+,mid+,r,l1,r1,v);
t[a].sum=t[a*].sum+t[a*+].sum;
return;
}
void pathmodify(int u,int v,int c){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]){int t=u;u=v;v=t;}
modify(,,n,pos[top[u]],pos[u],c);
u=fa[top[u]];
}
if(dep[u]>dep[v]){int t=u;u=v;v=t;}
modify(,,n,pos[u],pos[v],c);
return;
}
inline void nodemodify(int u,int c){
modify(,,n,pos[u],pos[u]+size[u]-,c);
}
int query(int a,int l,int r,int l1,int r1){//线段树区间和
if(r1<l||l1>r)return ;
if(l1<=l&&r<=r1)return t[a].sum;
int mid=(l+r)>>;
pushdown(a,l,r);
return query(a*,l,mid,l1,r1)+query(a*+,mid+,r,l1,r1);
}
int pathquery(int u,int v){//询问(u,v)这条路径的和
if(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]){int t=u;u=v;v=t;}
return pos[u]-pos[top[u]]+
+pathquery(fa[top[u]],v)-query(,,n,pos[top[u]],pos[u]);
}
if(dep[u]>dep[v]){int t=u;u=v;v=t;}
return pos[v]-pos[u]+-query(,,n,pos[u],pos[v]);
}
inline int nodequery(int u){
return query(,,n,pos[u],pos[u]+size[u]-);
}
void init(){
dep[]=fa[]=;
dfs1();
top[]=idx[]=pos[]=;
tot=;
dfs2(,);
for(int i=;i<*n;i++)t[i].lazy=-;
return;
}
int main(){
n=read();
for(int i=;i<=n;i++){
int v=read()+;
add(i,v);add(v,i);
}
init();
int q=read();
while(q--){
char op[];
scanf("%s",op);
int u=read()+;
if(op[]=='i'){
printf("%d\n",pathquery(u,));
pathmodify(u,,);
}
else{
printf("%d\n",nodequery(u));
nodemodify(u,);
}
}
return ;
}
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++
BZOJ4196:[NOI2015]软件包管理器——题解的更多相关文章
- [UOJ#128][BZOJ4196][Noi2015]软件包管理器
[UOJ#128][BZOJ4196][Noi2015]软件包管理器 试题描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管 ...
- [BZOJ4196][NOI2015]软件包管理器(树链剖分)
4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2166 Solved: 1253[Submit][Sta ...
- [BZOJ4196][NOI2015]软件包管理器
4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1040 Solved: 603[Submit][Stat ...
- 【NOI2015】【BZOJ4196】软件包管理器 - 题解
Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖( ...
- [bzoj4196][Noi2015]软件包管理器_树链剖分_线段树
软件包管理器 bzoj-4196 Noi-2015 题目大意:Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件 ...
- BZOJ4196 [Noi2015]软件包管理器 【树剖】
题目 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件 ...
- BZOJ4196[Noi2015]软件包管理器——树链剖分+线段树
题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个 ...
- BZOJ4196: [Noi2015]软件包管理器(树链剖分)
Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖( ...
- [Noi2015]软件包管理器 题解
题目大意: 有n个软件安装包,除第一个以外,其他的要在另一个安装包的基础上安装,且无环,问在安装和卸载某个软件包时,这个操作实际上会改变多少个软件包的安装状态. 思路: 可构成树,用树链剖分,线段树. ...
随机推荐
- /proc/meminfo详解
cat /proc/meminfo 读出的内核信息进行解释, 下篇文章会简单对读出该信息的代码进行简单的分析. MemTotal: 507480 kB MemFree: ...
- Ceph性能优化
几个 Ceph 性能优化的新方法和思路(2015 SH Ceph Day 参后感) 一周前,由 Intel 与 Redhat 在10月18日联合举办了 Shanghai Ceph Day.在这次会议上 ...
- C++11 type_traits 之is_pointer,is_member_function_pointer源码分析
源码如下: template<typename> struct __is_pointer_helper : public false_type { }; template<typen ...
- TW实习日记:第31-32天
不知不觉的,实习的净工作天数,已经都超过一个月了.因为对工作内容不是很满意,所以打算月底离职,也不知道是公司太缺人还是我真的能干活,领导竟然三番两次找我让我再考虑...明天又要找我了,哎...随机应变 ...
- 209. First Unique Character in a String
Description Find the first unique character in a given string. You can assume that there is at least ...
- FastJson 序列化与反序列化一些说明
最近所属的组需要对接一些征信结构,就涉及到很多中的数据格式,而springmvc中使用的是jackson作为@ResponseBody的依赖jar 但是个人认为fastkson的性能要高于jackso ...
- [Clr via C#读书笔记]Cp5基元类型引用类型值类型
Cp5基元类型引用类型值类型 基元类型 编译器直接支持的类型,基元类型直接映射到FCL中存在的类型. 作者希望使用FCL类型名称而避免使用关键字.他的理由是为了更加的清晰的知道自己写的类型是哪种.但是 ...
- Python基础 之 tuple类-元组 和 dict类-字典
tuple 元组 一.tuple 类的基本属性 1.元组,有序:元素不可被修改,不能被增加或者删除tuple类 tu = (111,22,33,44) 一般写元组的时候,推荐在最后加入,和类方法进行区 ...
- matlab中设置colorbar为几种规定颜色
我们可以通过修改colormap的值来达到这种目的. 一般来说colormap的值是64*3的矩阵,64代表64种颜色,3列是这种颜色的RGB值,不过归一化了. 如果你想将colorbar颜色设成6种 ...
- nginx 应用篇
nginx 信号控制(commanLine) kill singel pid ps aux|grep nginx nginx 有两个进程,一个 master 一个worker 一个master管理一 ...