题目大意

​ 给你一棵树, 求一点到根的路径上有多少个未标记点并全标记, 和询问一个点的子树内有多少已标记点和撤销标记

解题方法

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]软件包管理器】的更多相关文章

  1. 题解 P2146 [NOI2015]软件包管理器

    P2146 [NOI2015]软件包管理器 感觉代码比其他题解更简洁qwq 树链剖分模板题 install x:将1~x的路径上的节点全部变成1(安装x需要先安装1~x) uninstall x:将x ...

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

    [题解][P2146 NOI2015]软件包管理器 实际上就是树链剖分板子题. 对于\(install\)操作,直接查询它到\(0\)节点有多少已经安装了的,再用总数减去它. 对于\(uninstal ...

  3. 洛谷 P2146 [NOI2015]软件包管理器 解题报告

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

  4. 洛谷 P2146 [NOI2015]软件包管理器 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例#1: 输出样例#1: 输入样例#2: 输出样例#2: 说明 说明 思路 AC代码 总结 题面 题目链接 P ...

  5. P2146 [NOI2015]软件包管理器

    题目链接:https://www.luogu.org/problemnew/show/P2146 题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安 ...

  6. 洛谷 P2146 [NOI2015]软件包管理器 (树链剖分模板题)

    题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个 ...

  7. 【luogu P2146 [NOI2015]软件包管理器】 题解

    题目链接:https://www.luogu.org/problemnew/show/P2146 变量名真毒瘤 我真的再也不把l,left,r,right弄反了 反向思维更好做一些 #include ...

  8. 洛谷P2146 [NOI2015]软件包管理器 题解 树链剖分+线段树

    题目链接:https://www.luogu.org/problem/P2146 本题涉及算法: 树链剖分: 线段树(区间更新及求和,涉及懒惰标记) 然后对于每次 install x ,需要将 x 到 ...

  9. 【题解】Luogu P2146 [NOI2015]软件包管理器

    题面:https://www.luogu.org/problemnew/lists?name=2146 这道题要用树链剖分,我博客里有对树链剖分的详细介绍 这道题就是树链剖分的模板,详细解释见程序. ...

  10. 洛谷P2146 [NOI2015]软件包管理器

    https://www.luogu.org/problemnew/show/P2146 传送门 简单的树链剖分......维护下当前安装了多少个包......修改后查询下就行了......附上极其丑陋 ...

随机推荐

  1. 【转】CentOS 7 安装配置 NFS

    环境 nps 192.168.1.97 client 192.168.1.98 一.yum 安装 yum -y install nfs-utils rpcbind nfs 的配置文件 /etc/exp ...

  2. 【转】Centos yum 换源

    [1] 首先备份/etc/yum.repos.d/CentOS-Base.repo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/Cent ...

  3. 2018.11.04 洛谷P1081 开车旅行(倍增)

    传送门 思路简单码量超凡? 感觉看完题大家应该都知道是倍增sbsbsb题了吧. 首先预处理出从每个点出发如果是AAA走到哪个点,如果是BBB走到哪个点. 然后利用刚刚预处理出的信息再预处理从每个点出发 ...

  4. 2018.11.02 洛谷P2312 解方程(数论)

    传送门 直接做肯定会TLETLETLE. 于是考验乱搞能力的时候到了. 我们随便选几个质数来checkcheckcheck合法解,如果一个数无论怎么checkcheckcheck都是合法的那么就有很大 ...

  5. 2018.11.01 NOIP训练 树的排列(树形dp)

    传送门 跟这道题差不多. 只不过是让权值小的儿子做权值大的儿子的父亲而已. 代码

  6. tp5,thinkphp5,隐藏index.php,隐藏入口文件

    一.找到/public/.htaccess文件 Apache: <IfModule mod_rewrite.c> Options +FollowSymlinks -Multiviews R ...

  7. load data会被当成一个事务处理ERROR 1197

    问题现象: l有一份csv格式的文件,大小在14G左右.max_binlog_cache_size=4G. 登录mysql实例,选择对应的表通过load data往指定表里导数.大概20分钟左右,报以 ...

  8. (记忆化搜索)数塔 (zznu 1271)

    http://acm.zznu.edu.cn/problem.php?id=1271 1271: 数塔 时间限制: 1 Sec  内存限制: 128 MB提交: 109  解决: 78[提交][状态] ...

  9. Northwind测试学习用数据库

    下载地址: https://northwinddatabase.codeplex.com/

  10. 初始Hbase

    Hbase 定义 HBase是一个开源的非关系型分布式数据库(NoSQL),它参考了谷歌的BigTable建模,实现 的编程语言为 Java. 是Apache软件基金会的Hadoop项目的一部分,运行 ...