题解 P2146 【[NOI2015]软件包管理器】
题目大意
给你一棵树, 求一点到根的路径上有多少个未标记点并全标记, 和询问一个点的子树内有多少已标记点和撤销标记
解题方法
1: install 操作
这个操作是求一点到根的路径上有多少个未标记点并全标记, 这种操作可以用树链剖分来解决,将已标记的点的权值设为1, 求和即可
2.uninstall 操作
这个操作询问一个点的子树内有多少已标记点和撤销标记, 同理上面的方法就好了。
代码实现
---------------------------------------------
#include <bits/stdc++.h>
using namespace std;
template<class T>
inline void read(T &a){
T s = 0, w = 1;
char c = getchar();
while(c < '0' || c > '9') {if(c == '-') w = -1; c =getchar();}
while(c >= '0' && c <= '9') {s = (s << 1) + (s << 3) + (c ^ 48); c = getchar();}
a = s * w;
}
#define maxn 200100
#define maxm 200100
static int n, m;
static int net[maxm], to[maxm], head[maxm], tot;
inline void add(int x, int y){
net[++tot] = head[x], head[x] = tot, to[tot] = y;
}
/*-----------------------------------------------------------*/
static int fat[maxn], size[maxn], deep[maxn];
static int son[maxn];
void dfs1(int x, int fa){
fat[x] = fa;
size[x] = 1;
son[x] = 0;
deep[x] = deep[fa] + 1;
for (int i = head[x];i;i = net[i]){
int v = to[i];
if(v == fa) continue;
dfs1(v, x);
size[x] += size[v];
if(size[v] > size[son[x]]) son[x] = v;
}
}
static int tid[maxn], hhd[maxn], cnt, top[maxn];
void dfs2(int x, int t, int fa){
tid[x] = ++cnt; hhd[cnt] = x; top[x] = t;
if(!son[x]) return;
top[x] = t;
dfs2(son[x], t, x);
for (int i = head[x];i;i = net[i]){
int v = to[i];
if(v == fa || v == son[x]) continue;
dfs2(v, v, x);
}
}
/*-----------------------------------------*/
static int Sum[maxn * 8], lazy[maxn * 8];
#define ls rt << 1
#define rs rt << 1 | 1
inline void push_down(int rt, int l, int r){
int mid = (l + r) / 2;
Sum[ls] = (mid - l + 1) * lazy[rt];
Sum[rs] = (r - (mid + 1) + 1) * lazy[rt];
lazy[ls] = lazy[rt]; lazy[rs] = lazy[rt];
lazy[rt] = -1;
}
int ans = 0;
int Query(int rt, int l, int r, int L, int R){
if(L <= l && r <= R){
return Sum[rt];
}
else{
int mid = (l + r) / 2;
if(lazy[rt] != -1) push_down(rt, l, r);
int ans = 0;
if(L <= mid) ans += Query(ls, l, mid, L, R);
if(R > mid) ans += Query(rs, mid + 1, r, L, R);
Sum[rt] = Sum[ls] + Sum[rs];
return ans;
}
}
void Change(int rt, int l, int r, int L, int R, int d){
if(L <= l && r <= R){
Sum[rt] = (r - l + 1) * d;
lazy[rt] = d;
}
else{
int mid = (l + r) / 2;
if(lazy[rt] != -1) push_down(rt, l, r);
if(L <= mid) Change(ls, l , mid, L, R, d);
if(R > mid) Change(rs, mid + 1, r, L, R, d);
Sum[rt] = Sum[ls] + Sum[rs];
}
}
inline int Query_path(int x, int y){
int fx = top[x], fy = top[y];
int ans = 0;
while(fx != fy){
if(deep[x] < deep[y]) swap(x, y), swap(fx, fy);
ans += Query(1, 1, n, tid[fx], tid[x]);
x = fat[fx];
fx = top[x];
}
if(tid[x] < tid[y]) swap(x, y), swap(fx, fy);
ans += Query(1, 1, n, tid[y], tid[x]);
return ans;
}
inline void Change_path(int x, int y, int d){
int fx = top[x], fy = top[y];
int ans = 0;
while(fx != fy){
if(deep[x] < deep[y]) swap(x, y), swap(fx, fy);
Change(1, 1, n, tid[fx], tid[x], d);
x = fat[fx];
fx = top[x];
}
if(tid[x] < tid[y]) swap(x, y);
Change(1, 1, n, tid[y], tid[x], d);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("p2146.in","r", stdin);
freopen("p2146.out","w", stdout);
#endif
memset(lazy, -1, sizeof(lazy));
read(n);
for (int i = 1; i <= n-1; i++){
int x;
read(x);
add(x + 1, i + 1); add(i + 1, x + 1);
}
read(m);
dfs1(1, 0);
dfs2(1,1,0);
// build(1, 1, n);
for (int i = 1; i <= m; i++){
string s;
cin>>s;
// cout<<s<<endl;
if(s == "install"){
int x;
read(x); x++;
// printf("ss %d\n",i);
int ans = Query_path(1, x);
printf("%d\n", deep[x] - ans);
Change_path(1, x, 1);
}
else{
int x = 0;
read(x); x++;
int ans = Query(1, 1, n, tid[x], tid[x] + size[x] - 1);
printf("%d\n", ans);
Change(1, 1, n, tid[x], tid[x] + size[x] - 1, 0);
}
}
return 0;
}
题解 P2146 【[NOI2015]软件包管理器】的更多相关文章
- 题解 P2146 [NOI2015]软件包管理器
P2146 [NOI2015]软件包管理器 感觉代码比其他题解更简洁qwq 树链剖分模板题 install x:将1~x的路径上的节点全部变成1(安装x需要先安装1~x) uninstall x:将x ...
- 【题解】NOI2015软件包管理器
[题解][P2146 NOI2015]软件包管理器 实际上就是树链剖分板子题. 对于\(install\)操作,直接查询它到\(0\)节点有多少已经安装了的,再用总数减去它. 对于\(uninstal ...
- 洛谷 P2146 [NOI2015]软件包管理器 解题报告
P2146 [NOI2015]软件包管理器 题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软 ...
- 洛谷 P2146 [NOI2015]软件包管理器 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例#1: 输出样例#1: 输入样例#2: 输出样例#2: 说明 说明 思路 AC代码 总结 题面 题目链接 P ...
- P2146 [NOI2015]软件包管理器
题目链接:https://www.luogu.org/problemnew/show/P2146 题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安 ...
- 洛谷 P2146 [NOI2015]软件包管理器 (树链剖分模板题)
题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个 ...
- 【luogu P2146 [NOI2015]软件包管理器】 题解
题目链接:https://www.luogu.org/problemnew/show/P2146 变量名真毒瘤 我真的再也不把l,left,r,right弄反了 反向思维更好做一些 #include ...
- 洛谷P2146 [NOI2015]软件包管理器 题解 树链剖分+线段树
题目链接:https://www.luogu.org/problem/P2146 本题涉及算法: 树链剖分: 线段树(区间更新及求和,涉及懒惰标记) 然后对于每次 install x ,需要将 x 到 ...
- 【题解】Luogu P2146 [NOI2015]软件包管理器
题面:https://www.luogu.org/problemnew/lists?name=2146 这道题要用树链剖分,我博客里有对树链剖分的详细介绍 这道题就是树链剖分的模板,详细解释见程序. ...
- 洛谷P2146 [NOI2015]软件包管理器
https://www.luogu.org/problemnew/show/P2146 传送门 简单的树链剖分......维护下当前安装了多少个包......修改后查询下就行了......附上极其丑陋 ...
随机推荐
- idea如何将项目以eclipse保存
会生成 提交到svn eclipse 导入 首先使用TortoiseSVN下载要导入的项目 导入 已经存在的maven 项目 clean install -DskipTests t ...
- 2019.01.09 bzoj3697: 采药人的路径(点分治)
传送门 点分治好题. 题意:给出一棵树,边分两种,求满足由两条两种边数相等的路径拼成的路径数. 思路: 考虑将边的种类转化成边权−1-1−1和111,这样就只用考虑由两条权值为000的路径拼成的路径数 ...
- 在 Linux/windows下 命令行中使用和执行 PHP 代码[交互式php]
[注释]在ubuntu下,升级php到7.1版本,虽然提示的是Interactive mode enabled, 但实际上可以直接书写命令,和interactive shell效果一样. 一:wind ...
- vba遗传算法之非一致性突变
http://www.docin.com/p-959323141-f4.html Sub 非一致性变异() Dim totalGenerate As Integer, currentGenerate ...
- reload maven project' has encountered a proble" 问题
由于重重原因,我取消maven的下载(可能是jar包没有公服镜像).导致重新打开sts 时发生异常. 在网上寻找到资料,发现需要删除${workspace}\.metadata\.plugins\or ...
- window下切换python
自己的win10装了2.7和3.6版本的python.本不想装2.7的,但node.js的C++的编译居然用到2.X的python,没法子就装了2.7.那怎么切换呢? 为了方便使用,我在系统的path ...
- classmethod,staticmethod
'''1 绑定方法: 在类内部定义的函数,默认就是给对象来用,而且是绑定给对象用的,称为对象的绑定方法 绑定对象的方法特殊之处: 应该由对象来调用,对象来调用,会自动将对象当作第一个参数传入 绑定到类 ...
- 关于Lambda
1. 查询时,包含关联子对象.如: 数据库中包含表Father和Son,映射实体如下: public class Father { public string Name{get;set;} publi ...
- day34(注解)
注解 注解和注释的区别: 注释:是给程序员看的. 注解:是给虚拟机识别的. 注解的作用: 1.代替配置文件 2.标识一个方法,代替一个特殊功能. JDK当中的提供的注解: 标识重写方法 @Overri ...
- UIKit-UIBezierPath
UIBezierPath精讲 http://www.henishuo.com/uibezierpath-draw/ iOS UIBezierPath类 介绍 http://justsee.iteye. ...