题目传送门;

  这个貌似是我这个蒟蒻做的第一道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. EasyUI Tree递归方式获取JSON

    最近需要用到EASYUI中的TREE功能,以前我是直接拼接成<UL><LI>发现这样拼完之后在更改树后对树的刷新不是很理想,现改用JSON格式,首先分析TREE中JOSN格式如 ...

  2. UVA 1640 The Counting Problem

    https://vjudge.net/problem/UVA-1640 题意:统计区间[l,r]中0——9的出现次数 数位DP 注意删除前导0 #include<cmath> #inclu ...

  3. redis 模糊查找keys

    Redis入门教程可参考:超强.超详细Redis数据库入门教程 Redis操作命令可参考:Redis操作命令总结 redis可以通过命令Keys Match来进行键值的模糊匹配,借助StackExch ...

  4. SQL Server Compact/SQLite Toolbox

    如果你的vs2013 无法打开 .sdf 数据库文件. 那么 SQL Server Compact/SQLite Toolbox,可以帮助你. 下载安装后, vs2013->tools-> ...

  5. Item 1----------考虑用静态工厂方法代替构造器

    读书,有时候,我感觉总是有点绕和不具体.我阅读了代码,理解代码后,才有一种理解和把握的感觉. 优点三.   把某个对象的构建放给客户端来实现. 比如下面的实现,客户端Test,获取Service的实例 ...

  6. 51nod 1106 质数检测——Mr判素数

    质数检测一般都是根号n的写法 当然Mr判素数的方法可以实现log的复杂度2333 Mr判素数的话 我们根据费马小定理只要P是素数 那么另一个素数x 满足 x^P-1≡1(mod P) 同时 x^2%P ...

  7. 【BZOJ】1709: [Usaco2007 Oct]Super Paintball超级弹珠

    [算法]模拟 [题解]O(n^2)预处理横线(y),纵线(x),主对角线(y-x+n),副对角线(x+y). 然后n^2枚举每个点.

  8. Java案例之随机验证码功能实现

    实现的功能比较简单,就是随机产生了四个字符然后输出.效果图如下,下面我会详细说一下实现这个功能用到了那些知识点,并且会把 这些知识点详细的介绍出来.哈哈 ,大神勿喷,对于初学Java的人帮助应该蛮大的 ...

  9. Python爬虫—破解JS加密的Cookie

    前言 在GitHub上维护了一个代理池的项目,代理来源是抓取一些免费的代理发布网站.上午有个小哥告诉我说有个代理抓取接口不能用了,返回状态521.抱着帮人解决问题的心态去跑了一遍代码.发现果真是这样. ...

  10. 函数导出在kvm_intel.ko,kvm.ko不共享

    KVM一共包含了三个内核模块,kvm_intel.ko,kvm_amd.ko,kvm.ko.其中两个重要文件x86.c和vmx.c在编译后分别会生成kvm_intel.ko和kvm.ko两个内核模块, ...