题面

解析

事实上,这应该是道树剖裸题了,

将已安装表示为\(1\),

那么只需要在线段树中记录一下区间中\(1\)的个数就行了.

在询问的时候,

如果是安装,就查询\(x\)到根节点,

卸载的话,就查询\(x\)的子树.

注意下细节就行了(最好整体位移一下).

感觉真的没什么讲的了qwq

上代码吧:

#include <iostream>
#include <cstdio>
#include <cstring>
#define ls(a) a<<1
#define rs(a) a<<1|1
using namespace std; inline int read(){
int sum=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){sum=sum*10+c-'0';c=getchar();}
return sum*f;
} struct edge{int to,next;}e[100001];
struct node{int dep,top,fa,son,size,id;}a[100001];
struct tree{int l,r,val,tag;}t[400001];
int n,m;
int head[100001],cnt=0;
int tot=0; inline void add(int x,int y){
e[++cnt]=(edge){head[x],y};head[x]=cnt;
} void dfs1(int x,int fa){
a[x].dep=a[fa].dep+1;a[x].fa=fa;a[x].size=1;
for(int i=head[x];i;i=e[i].to){
int k=e[i].next;if(k==fa) continue;
dfs1(k,x);a[x].size+=a[k].size;
if(!a[x].son||a[a[x].son].size<a[k].size) a[x].son=k;
}
} void dfs2(int x,int t){
a[x].id=++tot;a[x].top=t;
if(a[x].son) dfs2(a[x].son,t);
for(int i=head[x];i;i=e[i].to){
int k=e[i].next;if(k==a[x].fa||k==a[x].son) continue;
dfs2(k,k);
}
} void pushup(int p){
t[p].val=t[ls(p)].val+t[rs(p)].val;
} void pushdown(int p){
if(!t[p].tag) return ;
int ls=ls(p),rs=rs(p);
t[ls].tag=t[rs].tag=t[p].tag;
if(t[p].tag==2) t[p].tag=0;
t[ls].val=t[p].tag*(t[ls].r-t[ls].l+1);
t[rs].val=t[p].tag*(t[rs].r-t[rs].l+1);
t[p].tag=0;
} void build(int p,int l,int r){
t[p].l=l;t[p].r=r;
if(l==r) return ;
int mid=(l+r)>>1;
build(ls(p),l,mid);build(rs(p),mid+1,r);
} void change(int p,int l,int r,int opt){
if(t[p].l>=l&&t[p].r<=r){
t[p].val=opt*(t[p].r-t[p].l+1);t[p].tag=opt;
if(!opt) t[p].tag=2;
return ;
}
pushdown(p);
int mid=(t[p].l+t[p].r)>>1;
if(l<=mid) change(ls(p),l,r,opt);
if(r>mid) change(rs(p),l,r,opt);
pushup(p);
} int ask1(int p,int l,int r){
if(t[p].l>=l&&t[p].r<=r) return t[p].val;
pushdown(p);
int mid=(t[p].l+t[p].r)>>1,ans=0;
if(l<=mid) ans+=ask1(ls(p),l,r);
if(r>mid) ans+=ask1(rs(p),l,r);
pushup(p);
return ans;
} int ask0(int p,int l,int r){
if(t[p].l>=l&&t[p].r<=r) return t[p].r-t[p].l+1-t[p].val;
pushdown(p);
int mid=(t[p].l+t[p].r)>>1,ans=0;
if(l<=mid) ans+=ask0(ls(p),l,r);
if(r>mid) ans+=ask0(rs(p),l,r);
pushup(p);
return ans;
} inline void work1(int x,int y,int opt){
int ans=ask1(1,a[x].id,a[x].id+a[x].size-1);
change(1,a[x].id,a[x].id+a[x].size-1,opt);
printf("%d\n",ans);
} inline void work0(int x,int y,int opt){
int ans=0;
while(a[x].top!=a[y].top){
if(a[a[x].top].dep<a[a[y].top].dep) swap(x,y);
ans+=ask0(1,a[a[x].top].id,a[x].id);
change(1,a[a[x].top].id,a[x].id,opt);x=a[a[x].top].fa;
}
if(a[x].dep>a[y].dep) swap(x,y);
ans+=ask0(1,a[x].id,a[y].id);change(1,a[x].id,a[y].id,opt);
printf("%d\n",ans);
} int main(){
n=read();
for(int i=2;i<=n;i++){int x=read()+1;add(x,i);}
m=read();
dfs1(1,0);dfs2(1,1);build(1,1,n);
for(int i=1;i<=m;i++){
string s;cin>>s;int x=read()+1;
if(s[0]=='u') work1(x,1,0);
else if(s[0]=='i') work0(x,1,1);
}
return 0;
}

题解 【NOI2015】软件包管理器的更多相关文章

  1. 【题解】NOI2015软件包管理器

    [题解][P2146 NOI2015]软件包管理器 实际上就是树链剖分板子题. 对于\(install\)操作,直接查询它到\(0\)节点有多少已经安装了的,再用总数减去它. 对于\(uninstal ...

  2. 题解 P2146 [NOI2015]软件包管理器

    P2146 [NOI2015]软件包管理器 感觉代码比其他题解更简洁qwq 树链剖分模板题 install x:将1~x的路径上的节点全部变成1(安装x需要先安装1~x) uninstall x:将x ...

  3. Bzoj 4196: [Noi2015]软件包管理器 树链剖分

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 721  Solved: 419[Submit][Statu ...

  4. 【BZOJ4196】[Noi2015]软件包管理器 树链剖分

    [Noi2015]软件包管理器 树链剖分 Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从 ...

  5. [UOJ#128][BZOJ4196][Noi2015]软件包管理器

    [UOJ#128][BZOJ4196][Noi2015]软件包管理器 试题描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管 ...

  6. BZOJ 4196: [Noi2015]软件包管理器 [树链剖分 DFS序]

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1352  Solved: 780[Submit][Stat ...

  7. [BZOJ4196][NOI2015]软件包管理器

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1040  Solved: 603[Submit][Stat ...

  8. [NOI2015]软件包管理器

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

  9. BZOJ_4196_[Noi2015]软件包管理器_树链剖分

    BZOJ_4196_[Noi2015]软件包管理器_树链剖分 题意: Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助 ...

  10. bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2852  Solved: 1668[Submit][Sta ...

随机推荐

  1. ARC100E. Or Plus Max

    题目 好题.没想出解法. 官方题解: 这个解法和 Small Multiple 那道题的解法有异曲同工之妙. 扩展 若把 $\mathsf{or}$ 改成 $\mathsf{and}$ 或者 $\ma ...

  2. Java中的责任链设计模式,太牛了!

    责任链设计模式的思想很简单,就是按照链的顺序执行一个个处理方法,链上的每一个任务都持有它后面那个任务的对象引用,以方便自己这段执行完成之后,调用其后面的处理逻辑. 下面是一个责任链设计模式的简单的实现 ...

  3. centos7搭建NFS服务

    服务器端 139.155.90.78 客户端  192.168.198.146 先查看自己的系统有没有安装rpcbind 和nfs-utils rpm -qa nfs-utils rpcbind 若使 ...

  4. Leetcode 杂题

    盛最多水的容器   给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) .在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) ...

  5. 怎样获取NodeList某位置上的节点

    1. 使用类似 Array 的中括号写法: document.body.childNodes[0] 2. 使用 NodeList.prototype.item(): document.body.chi ...

  6. 修改git默认的编辑器nano为vim的方法

    git默认的编辑器是nano,使用起来不易操作,下面介绍两种方法将git默认的编辑器修改为vim.  git config --global core.editor vim .git/config文件 ...

  7. 【原创】大叔经验分享(63)kudu vs parquet

    一 对比 存储空间对比: 查询性能对比: 二 设计方案 将数据拆分为:历史数据(hdfs+parquet+snappy)+ 近期数据(kudu),可以兼具各种优点: 1)整体低于10%的磁盘占用: 2 ...

  8. 养成一个SQL好习惯

    要知道sql语句,我想我们有必要知道sqlserver查询分析器怎么执行我么sql语句的,我么很多人会看执行计划,或者用profile来监视和调优查询语句或者存储过程慢的原因,但是如果我们知道查询分析 ...

  9. Mongodb安装后在任务管理器中找不到这个服务

    今天安装mongodb,但是一开始在任务管理器中找不到这个服务,后来查询得知:稍微高一些的系统是需要通过管理员身份运行cmd命令行安装的. orz,找了好久才知道是这个问题. 2333 在任务管理的服 ...

  10. python 匿名函数lambda使用

    lambda函数语法格式: lambda函数 后面参数可以有一个或多个,冒号后面是python表达式: lambda 参数1,参数2,参数3...:表达式 # 一个参数情况: a = lambda x ...