题解 【NOI2015】软件包管理器
题面
解析
事实上,这应该是道树剖裸题了,
将已安装表示为\(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】软件包管理器的更多相关文章
- 【题解】NOI2015软件包管理器
		[题解][P2146 NOI2015]软件包管理器 实际上就是树链剖分板子题. 对于\(install\)操作,直接查询它到\(0\)节点有多少已经安装了的,再用总数减去它. 对于\(uninstal ... 
- 题解 P2146 [NOI2015]软件包管理器
		P2146 [NOI2015]软件包管理器 感觉代码比其他题解更简洁qwq 树链剖分模板题 install x:将1~x的路径上的节点全部变成1(安装x需要先安装1~x) uninstall x:将x ... 
- Bzoj 4196: [Noi2015]软件包管理器  树链剖分
		4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 721 Solved: 419[Submit][Statu ... 
- 【BZOJ4196】[Noi2015]软件包管理器 树链剖分
		[Noi2015]软件包管理器 树链剖分 Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从 ... 
- [UOJ#128][BZOJ4196][Noi2015]软件包管理器
		[UOJ#128][BZOJ4196][Noi2015]软件包管理器 试题描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管 ... 
- BZOJ 4196: [Noi2015]软件包管理器 [树链剖分 DFS序]
		4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1352 Solved: 780[Submit][Stat ... 
- [BZOJ4196][NOI2015]软件包管理器
		4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1040 Solved: 603[Submit][Stat ... 
- [NOI2015]软件包管理器
		4621 [NOI2015]软件包管理器 题目等级 : 钻石 Diamond 题目描述 Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过 ... 
- BZOJ_4196_[Noi2015]软件包管理器_树链剖分
		BZOJ_4196_[Noi2015]软件包管理器_树链剖分 题意: Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助 ... 
- bzoj 4196  [Noi2015]软件包管理器 (树链剖分+线段树)
		4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2852 Solved: 1668[Submit][Sta ... 
随机推荐
- 在ASP.NET Core 2.0中使用Facebook进行身份验证
			已经很久没有更新自己的技术博客了,自从上个月末来到天津之后把家安顿好,这个月月初开始找工作,由于以前是做.NET开发的,所以找的还是.NET工作,但是天津这边大多还是针对to B(企业)进行定制开发的 ... 
- Linux系列(1):入门之基本命令详解
			Linux常用命令 声明: 作者使用的Linux是CentOS7版本. 本节主要讲解内容: 1.ls.date.bc.cal等指令的详细用法 2.介绍常用快捷键 3.了解磁盘分区以及挂载等概念 在Li ... 
- Linux中设置系统时间和时区
			之前公司里有需求要做机器与服务器做时间同步,服务器发送时间戳和时区过来,机器这边根据接收到的时间戳和时区来改时间. 其实很简单,百度上应该也有很多博客有类似的教程,但是这里强调一点,百度上的博客里写的 ... 
- 怎样理解HTMLCollection接口
			和 NodeList 类似, HTMLCollection 也是一个 类数组对象, 和NodeList不同的是, 它是各种 元素节点 的集合, 且不具有 forEach() 方法, 因此如果不转为真正 ... 
- MapReduces计数实验
			实验内容 现有某电商网站用户对商品的收藏数据,记录了用户收藏的商品id以及收藏日期,名为buyer_favorite1. buyer_favorite1包含:买家id,商品id,收藏日期这三个字段,数 ... 
- asp.net 8 Request,Response,Server
			Request成员: 1.Request.UrlReferrer 获取请求的来源,可以防盗链 Response.Write(Request.Url.ToString());//获取当前请求的URL地址 ... 
- vim insert VISUAL模式无法右键复制问题(转)
			转自:https://blog.csdn.net/coder_oyang/article/details/89096219 vim中使用鼠标右键粘贴,失败.vim的模式: 网上解法: 1. 普通模式下 ... 
- 页面加载时调用js函数方法
			方法一:在html的body中加入onload=""事件 <body onload='queryServer()'> </body> 方法二:jquery ... 
- MYSQL 修改语句(数据)
			修改数据(UPDATE) 如果你失忆了,希望你能想起曾经为了追求梦想的你. 我们玩QQ.微信.淘宝等等,都会有一个操作:修改信息 淘宝常用的嘛,新增了收货地址,也可以修改它,微信/ ... 
- Nginx作为代理服务之反向代理
			Nginx作为代理服务之反向代理 需求:我们需要访问一个服务,但是服务端只接受8080端口,所以需要在nginx中配置反向代理,帮助客户端代理实现. 1. 创建一个html放入到一个文件夹中 2. 在 ... 
