题目传送门;

  这个貌似是我这个蒟蒻做的第一道NOI系列的题了吧。。。这题的算法是树链剖分,其实基本上就是很常见的树剖+线段树,题目既然是要求每次安装或卸载改变的软件包的数目,那么就在每次操作前记录下线段树中根节点的权值,再进行修改,修改后的根节点的值与先前记录的值的差的绝对值就是改变的软件包的数目。思想并不复杂,但是这一类代码量比较大的题有很多细节要注意,这里我就不一一地说了。

  另外,这个题目中的软件包是从0开始标号的,为了方便操作,可以把所有软件包的标号都+1。

  下面是AC代码:

  (蒟蒻手写的代码效率也还行,最慢的点236ms)  

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=;
int n,m,anum,depth[N],head[N];
int xu[N],id,num[N],fa[N];
int size[N],top[N],hson[N];
int segtree[N<<],sign[N<<];
struct Node{
int to,next;
}edge[N<<];
inline int read()
{
char ch=getchar();int num=;bool flag=false;
while(ch<''||ch>''){if(ch=='-')flag=true;ch=getchar();}
while(ch>=''&&ch<=''){num=num*+ch-'';ch=getchar();}
return flag?-num:num;
}
inline int Abs(int x)
{return x>?x:-x;}
inline void add(int x,int y)
{
edge[++anum].to=y;
edge[anum].next=head[x];
head[x]=anum;
}
inline void dfs1(int u)
{
size[u]=;
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].to;
if(v==fa[u])continue;
depth[v]=depth[u]+;fa[v]=u;
dfs1(v);size[u]+=size[v];
if(!hson[u]||size[v]>size[hson[u]])
hson[u]=v;
}
}
inline void dfs2(int u,int nowtop)
{
xu[++id]=u;num[u]=id;top[u]=nowtop;
if(!hson[u])return;dfs2(hson[u],nowtop);
for(int i=head[u];i!=-;i=edge[i].next){
int v=edge[i].to;
if(v==fa[u]||v==hson[u])continue;
dfs2(v,v);
}
}
inline void pushup(int root)
{segtree[root]=segtree[root<<]+segtree[root<<|];}
inline void pushdown(int root,int l,int r)
{
if(sign[root]!=-){
int mid=(l+r)>>;
segtree[root<<]=(mid-l+)*sign[root];
segtree[root<<|]=(r-mid)*sign[root];
sign[root<<]=sign[root];
sign[root<<|]=sign[root];
sign[root]=-;
}
}
inline void build(int l,int r,int root)
{
segtree[root]=;
if(l==r)return;
int mid=(l+r)>>;
build(l,mid,root<<);
build(mid+,r,root<<|);
pushup(root);
}
inline void update(int l,int r,int root,int L,int R,int C)
{
if(r<L||l>R)return;
if(L<=l&&r<=R){
segtree[root]=(r-l+)*C;
sign[root]=C;return;}
int mid=(l+r)>>;
pushdown(root,l,r);
if(L<=mid)update(l,mid,root<<,L,R,C);
if(R>mid)update(mid+,r,root<<|,L,R,C);
pushup(root);
}
inline void change(int x,int y,int val)
{
int fax=top[x],fay=top[y];
while(fax!=fay){
if(depth[fax]<depth[fay])
{swap(fax,fay);swap(x,y);}
update(,n,,num[fax],num[x],val);
x=fa[fax];fax=top[x];
}
if(depth[x]>depth[y])swap(x,y);
update(,n,,num[x],num[y],val);
}
void ready()
{
memset(head,-,sizeof(head));
memset(sign,-,sizeof(sign));
n=read();
for(int i=;i<n;i++){
int x=read();
add(i+,x+);
add(x+,i+);
}
fa[]=;depth[]=;
dfs1();dfs2(,);
build(,n,);
}
void work()
{
m=read();char ka[];
for(int i=;i<=m;i++){
scanf("%s",ka);
int t1=segtree[];
int x=read();x++;
if(ka[]=='i'){
change(,x,);
int t2=segtree[];
printf("%d\n",Abs(t2-t1));
}
if(ka[]=='u'){
update(,n,,num[x],num[x]+size[x]-,);
int t2=segtree[];
printf("%d\n",Abs(t1-t2));
}
}
}
int main()
{
ready();
work();
return ;
}

NOI2015 D1T2 软件包管理器的更多相关文章

  1. 【BZOJ4196】【NOI2015】软件包管理器(树链剖分,线段树)

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

  2. BZOJ_4196_[NOI2015]_软件包管理器_(树链剖分)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=4196 给出一棵树,树上点权为0或1.u权值为1的条件是从根节点到u路径上的所有点权值都为1.u ...

  3. 【NOI2015】 软件包管理器 - 树链剖分

    noi2015 软件包管理器 Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软 ...

  4. 【NOI2015】软件包管理器

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

  5. 【BZOJ4196】【Noi2015】软件包管理器

    原题传送门 题意: 给你一棵树,有2种操作: 1.使得某个点到根节点路径上的所有点权值赋为1. 2.使得某节点的子树中所有节点权值赋为0. 每次操作要求输出权值更改的节点个数. 解题思路: 显然是用树 ...

  6. 【LOJ】 #2130. 「NOI2015」软件包管理器

    题解 连树剖我都写跪一次,我现在怎么那么老年啊= = 简直滚粗预定了啊.. 我们线段树维护树剖只需要资瓷区间覆盖和区间求和就好了 安装的时候看看自己到根有多少包装了,dep减去这个数量就好 卸载的时候 ...

  7. LibreOJ #2130. 「NOI2015」软件包管理器

    内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 上传者: 匿名 树链剖分+线段树 屠龙宝刀点击就送 #include <vector> ...

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

    题面 解析 事实上,这应该是道树剖裸题了, 将已安装表示为\(1\), 那么只需要在线段树中记录一下区间中\(1\)的个数就行了. 在询问的时候, 如果是安装,就查询\(x\)到根节点, 卸载的话,就 ...

  9. 「NOI2015」软件包管理器

    题目描述 题面比较啰唆,我先把大体意思讲一下: 首先,有编号从\(0\)到\(N-1\)的\(N\)个节点,根节点一定是\(0\)号节点(无前驱) (我把下标都加上了一,转化为以\(1\)为起始下标的 ...

随机推荐

  1. 更改本地hosts文件

    在 C:\Windows\System32\drivers\etc 下更改 hosts 文件 127.0.0.1 www.baidu.com 这样访问 www.baidu.com 这个地址,其实是访问 ...

  2. [LeetCode] 6. ZigZag Conversion ☆☆☆

    The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like ...

  3. MongoDB入门(1)- MongoDB简介

    什么是MongoDB NoSQL NoSQL systems are also sometimes called "Not only SQL" to emphasize that ...

  4. Java中xml2json,json2xml

    在JAVA中xml与json数据互相转换 package com.sgcc.platform.common.utils; import static java.lang.String.format; ...

  5. 增强学习Reinforcement Learning经典算法梳理3:TD方法

    转自:http://blog.csdn.net/songrotek/article/details/51382759 博客地址:http://blog.csdn.net/songrotek/artic ...

  6. 【Android】完善Android学习(二:API 2.3.4)

    备注:之前Android入门学习的书籍使用的是杨丰盛的<Android应用开发揭秘>,这本书是基于Android 2.2API的,目前Android已经到4.4了,更新了很多的API,也增 ...

  7. [洛谷P4774] [NOI2018]屠龙勇士

    洛谷题目链接:[NOI2018]屠龙勇士 因为markdown复制过来有点炸格式,所以看题目请戳上面. 题解: 因为杀死一条龙的条件是在攻击\(x\)次,龙恢复\(y\)次血量\((y\in N^{* ...

  8. git设置免密码登录

    设置用户名和邮箱 git config --global user.name "<username>" git config --global user.email & ...

  9. 五分钟学习Java8的流编程

    1.概述 Java8中在Collection中增加了一个stream()方法,该方法返回一个Stream类型.我们就是用该Stream来进行流编程的: 流与集合不同,流是只有在按需计算的,而集合是已经 ...

  10. Angular2.0 基础: 环境搭建

    最近在学习Angular2的使用,其实看过Angular2 文档的都知道,相比于之前的Angular1,Angular2 的改动还是挺大的. 而对于‘angular2 的本地开发环境的搭建的中,我们首 ...