题目大意

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

解题方法

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. MacBook小技巧

    退出全屏:Control+Command+F.关闭当前的应用程序:Command+W.退出应用程序,可对着Dock上的应用程序辅助点按(右键),选择退出.也可直接按Commnad+Q退出当前的应用程序 ...

  2. 2018.12.08 codeforces 914D. Bash and a Tough Math Puzzle(线段树)

    传送门 线段树辣鸡题. 题意简述:给出一个序列,支持修改其中一个数,以及在允许自行修改某个数的情况下询问区间[l,r][l,r][l,r]的gcdgcdgcd是否可能等于一个给定的数. 看完题就感觉是 ...

  3. Opencv(3):基本数据类型

    1.比较简单的原子类型 结构 成员 意义 CvPoint int x,y 图像中的点 CvPoint2D32f float x,y 二维空间中的点 CvPoint3D32f float x,y,z 三 ...

  4. java中正则表达式常用方法

    一.匹配 String  matches()方法.用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false. 举例: public static void checkQQ(){ Stri ...

  5. Amaze UI 云适配

    Amaze UI  云适配 陈本峰  一中,中科大 香港科大

  6. SQL中的split方法的使用

    参数说明: 1.@String :需要split的字符串 2.@Delimiter :格式化时分隔符 3.@index :返回split后数组的值 ), ),)) ) AS BEGIN )) ) DE ...

  7. Ubuntu 16.04 搭建LAMP服务器环境流程

    http://www.linuxidc.com/Linux/2016-09/135629.htm [安装mysql时 只需安装 mysql-server无需安装mysql-client] mysql ...

  8. JAVA经典算法40+

    现在是3月份,也是每年开年企业公司招聘的高峰期,同时有许多的朋友也出来找工作.现在的招聘他们有时会给你出一套面试题或者智力测试题,也有的直接让你上机操作,写一段程序.算法的计算不乏出现,基于这个原因我 ...

  9. 学以致用七---Centos7.2+python3.6.2+django2.1.1 --搭建一个网站(补充)

    补充:上一节出现的报错提示 可在settings.py 里,改成 ‘*’  ,这样所有的主机都可以访问了. 打开网页 注意红色框出来的 hello 是和 urls.py里的hello对应 urls.p ...

  10. 在IIS7.5下配置PHP环境

    1.下载安装ZkeysPHP,路径随意 找到该程序集 D:\ZkeysSoft\Php\php5isapi.dll 2.在站点配置“处理程序映射”,添加php后缀映射由D:\ZkeysSoft\Php ...