题目大意

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

解题方法

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. MES制造执行系统

    mes :  Manufacturing Execution System 制造执行系统 起因:ERP系统和底层设备之间出现了断层. 包括资源管理,生产调度,单元分配,生产跟踪,性能分析,文档管理,人 ...

  2. CHAPITRE II

    J'ai ainsi vécu seul, sans personne avec qui parler véritablement, jusqu'à une panne[pan][机]故障 dans ...

  3. boost--线程

     1.thread的使用 boost的thread包含了线程创建.使用.同步等内容,使用thread需要包含头文件"boost\thread.hpp". thread中使用了需要编 ...

  4. 枚举子窗口EnumChildWindows()的应用

    1.EnumChildWindows()函数的作用枚举子窗口(按顺序调用回调函数,并将子窗口的句柄传递给了回调函数).函数原型: BOOL WINAPI EnumChildWindows( HWND ...

  5. python3.4读取excel数据绘图

    #!/usr/bin/env python # -*- coding:utf-8 -*- # __author__ = "blzhu" """ pyt ...

  6. Oracle数据库常用的sql语句

    1. select * from emp; 2. select empno, ename, job from emp; 3. select empno 编号, ename 姓名, job 工作 fro ...

  7. silverlight 父窗体传值给ChildWindow

    在网上找了许多列子,有的没有看懂,有的太麻烦. 现在有两种方法又简单又实用的,分享给大家! 第一种:使用构造函数传值 1.子页面新建一个构造函数 public ChildWindowTest(stri ...

  8. Ubuntu下安装并配置TexStudio

    作者:tongqingliu 转载请注明出处:http://www.cnblogs.com/liutongqing/p/7069715.html Ubuntu下安装并配置TexStudio Ubunt ...

  9. leetcode-[3]Max Points on a Line

    Given n points on a 2D plane, find the maximum number of points that lie on the same straight line 思 ...

  10. springMvc里的mvc:resources与静态资源的访问

    在进行Spring MVC的配置时,通常我们会配置一个dispatcher servlet用于处理对应的URL.配置如下:   <servlet>   <servlet-name&g ...