NOI2015 D1T2 软件包管理器
这个貌似是我这个蒟蒻做的第一道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 软件包管理器的更多相关文章
- 【BZOJ4196】【NOI2015】软件包管理器(树链剖分,线段树)
[BZOJ4196][NOI2015]软件包管理器 题面 题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你 ...
- BZOJ_4196_[NOI2015]_软件包管理器_(树链剖分)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=4196 给出一棵树,树上点权为0或1.u权值为1的条件是从根节点到u路径上的所有点权值都为1.u ...
- 【NOI2015】 软件包管理器 - 树链剖分
noi2015 软件包管理器 Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软 ...
- 【NOI2015】软件包管理器
NOI难得的水题,话说还是T2诶……又学到了线段树的一种新的魔性使用 看sxysxy大神的代码才写出来的,sxysxy_orz 原题: Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包 ...
- 【BZOJ4196】【Noi2015】软件包管理器
原题传送门 题意: 给你一棵树,有2种操作: 1.使得某个点到根节点路径上的所有点权值赋为1. 2.使得某节点的子树中所有节点权值赋为0. 每次操作要求输出权值更改的节点个数. 解题思路: 显然是用树 ...
- 【LOJ】 #2130. 「NOI2015」软件包管理器
题解 连树剖我都写跪一次,我现在怎么那么老年啊= = 简直滚粗预定了啊.. 我们线段树维护树剖只需要资瓷区间覆盖和区间求和就好了 安装的时候看看自己到根有多少包装了,dep减去这个数量就好 卸载的时候 ...
- LibreOJ #2130. 「NOI2015」软件包管理器
内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 上传者: 匿名 树链剖分+线段树 屠龙宝刀点击就送 #include <vector> ...
- 题解 【NOI2015】软件包管理器
题面 解析 事实上,这应该是道树剖裸题了, 将已安装表示为\(1\), 那么只需要在线段树中记录一下区间中\(1\)的个数就行了. 在询问的时候, 如果是安装,就查询\(x\)到根节点, 卸载的话,就 ...
- 「NOI2015」软件包管理器
题目描述 题面比较啰唆,我先把大体意思讲一下: 首先,有编号从\(0\)到\(N-1\)的\(N\)个节点,根节点一定是\(0\)号节点(无前驱) (我把下标都加上了一,转化为以\(1\)为起始下标的 ...
随机推荐
- CodeBlocks wrong
codeblocks官网 Q1. 中文乱码 系统是win,用的是codeblocks编辑器,指定的原文件编码是UTF-8 编译后运行,发现中文在控制台里显示全是乱码 A1: 对此有解决办法,通过给g+ ...
- [洛谷P3628] [APIO2010]特别行动队
洛谷题目链接:[APIO2010]特别行动队 题目描述 你有一支由 n 名预备役士兵组成的部队,士兵从 1 到 \(n\) 编号,要将他们拆分 成若干特别行动队调入战场.出于默契的考虑,同一支特别行动 ...
- [Luogu 1168] 中位数
中位数可以转化为区间第k大问题,当然是选择Treap实现名次树了啊.(笑) 功能十分简单的Treap即能满足需求--只需要插入与查找第大的功能. 插入第i个数时,如果i是奇数,随即询问当前排名第(i+ ...
- pythonweb框架
https://www.cnblogs.com/sss4/p/8097653.html
- hdu 2157 How many ways?? ——矩阵十题第八题
Problem Description 春天到了, HDU校园里开满了花, 姹紫嫣红, 非常美丽. 葱头是个爱花的人, 看着校花校草竞相开放, 漫步校园, 心情也变得舒畅. 为了多看看这迷人的校园, ...
- Java并发——关键字synchronized解析
synchronized用法 在Java中,最简单粗暴的同步手段就是synchronized关键字,其同步的三种用法: ①.同步实例方法,锁是当前实例对象 ②.同步类方法,锁是当前类对象 ③.同步代码 ...
- 抓其根本(一)(hdu2710 Max Factor 素数 最大公约数 最小公倍数.....)
素数判断: 一.根据素数定义,该数除了1和它本身以外不再有其他的因数. 详见代码. int prime() { ; i*i<=n; i++) { ) //不是素数 ; //返回1 } ; //是 ...
- perl中的lock
#!/usr/bin/env perl -w use strict; use threads; use threads::shared; ; print "count的起始值为:$count ...
- mysql 数据库修改名字
通过information_schema信息修改rename database的目的 mysql 没有rename database 命令,只能变相修改表到目标库里的表来实现: 拼接reanme ta ...
- xtrabackup 安装、备份和恢复
xtrabackup 版本对应: 2.4 专针对 5.7 开发的,兼容 5.6, 5.5 2.3 针对 5.6 开发的,兼容5.5 2.2 针对5.5 开发的 安装包下载: wget https:// ...