【luogu P2146 [NOI2015]软件包管理器】 题解
题目链接:https://www.luogu.org/problemnew/show/P2146
变量名真毒瘤 我真的再也不把l,left,r,right弄反了
反向思维更好做一些
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define lson left, mid, rt<<1
#define rson mid + 1, right, rt<<1|1
using namespace std;
const ll maxn = 100000 + 10;
char opt[9];
ll n, m, root, res;
ll fa[maxn], deep[maxn], size[maxn], top[maxn], son[maxn], seg[maxn], rev[maxn], num;
ll tree[maxn<<2], lazy[maxn<<2];
struct edge{
ll to, next;
}e[maxn<<2];
ll head[maxn], cnt;
void add(ll u, ll v)
{
e[++cnt].next = head[u];
e[cnt].to = v;
head[u] = cnt;
}
//-----segment_tree-----
void PushUP(ll rt)
{
tree[rt] = tree[rt<<1] + tree[rt<<1|1];
}
void build(ll left, ll right, ll rt)
{
lazy[rt] = -1;
if(left == right)
{
tree[rt] = 1;
return;
}
ll mid = (left + right)>>1;
build(lson);
build(rson);
PushUP(rt);
}
void PushDOWN(ll left, ll right, ll rt, ll mid)
{
lazy[rt<<1] = lazy[rt];
lazy[rt<<1|1] = lazy[rt];
tree[rt<<1] = lazy[rt]*(mid - left + 1);
tree[rt<<1|1] = lazy[rt]*(right - mid);
lazy[rt] = -1;
}
void update(ll l, ll r, ll add, ll left, ll right, ll rt)
{
if(l <= left && r >= right)
{
tree[rt] = add*(right - left + 1);
lazy[rt] = add;
return;
}
ll mid = (left + right)>>1;
if(lazy[rt] != -1) PushDOWN(left, right, rt, mid);
if(l <= mid) update(l,r,add,lson);
if(r > mid) update(l,r,add,rson);
PushUP(rt);
}
ll query(ll l, ll r, ll left, ll right, ll rt)
{
ll res = 0;
if(l <= left && r >= right)
{
return tree[rt];
}
ll mid = (left + right)>>1;
if(lazy[rt] != -1) PushDOWN(left, right, rt, mid);
if(l <= mid) res += query(l,r,lson);
if(r > mid) res += query(l,r,rson);
return res;
}
//----------------------
void dfs1(ll u, ll f, ll d)
{
ll maxson = -1;
size[u] = 1;
deep[u] = d;
fa[u] = f;
for(ll i = head[u]; i != -1; i = e[i].next)
{
ll v = e[i].to;
if(f != v)
{
dfs1(v, u, d+1);
size[u] += size[v];
if(maxson < size[v]) son[u] = v, maxson = size[v];
}
}
}
void dfs2(ll u, ll t)
{
seg[u] = ++num;
rev[num] = 1;
top[u] = t;
if(!son[u]) return;
dfs2(son[u], t);
for(ll i = head[u]; i != -1; i = e[i].next)
{
ll v = e[i].to;
if(v == son[u] || v == fa[u]) continue;
dfs2(v, v);
}
}
ll qRange(ll x, ll y)
{
ll ans = 0;
while(top[x] != top[y])
{
if(deep[top[x]] < deep[top[y]]) swap(x, y);
res = 0;
res = query(seg[top[x]], seg[x], 1, n, 1);
ans = ans + res;
x = fa[top[x]];
}
if(deep[x] > deep[y]) swap(x, y);
res = 0;
res = query(seg[x], seg[y], 1, n, 1);
ans = ans + res;
return ans;
}
void updRange(ll x, ll y, ll k)
{
while(top[x] != top[y])
{
if(deep[top[x]] < deep[top[y]]) swap(x, y);
update(seg[top[x]], seg[x], k, 1, n, 1);
x = fa[top[x]];
}
if(deep[x] > deep[y]) swap(x, y);
update(seg[x], seg[y], k, 1, n, 1);
}
ll qSon(ll x)
{
res = 0;
res = query(seg[x], seg[x]+size[x]-1, 1, n, 1);
return res;
}
void updSon(ll x, ll y)
{
update(seg[x], seg[x]+size[x]-1, y, 1, n, 1);
}
int main()
{
memset(lazy, -1, sizeof(lazy));
memset(head, -1, sizeof(head));
scanf("%lld",&n); root = 1;
for(ll i = 2; i <= n; i++)
{
ll u;
scanf("%lld",&u);u++;
add(u, i), add(i,u);
}
dfs1(root, 0, 1);
dfs2(root, root);
build(1, n, 1);
//for(ll i = 1; i <= n; i++) cout<<seg[i]<<" ";
scanf("%lld",&m);
for(ll i = 1; i <= m; i++)
{
ll u;
cin>>opt;
if(opt[0] == 'i')
{
scanf("%lld",&u);u++;
printf("%lld\n",qRange(u, root));
updRange(u, root, 0);
}
else
{
scanf("%lld",&u);u++;
//cout<<qSon(u)<<"qwq\n";
printf("%lld\n",size[u]-qSon(u));
updSon(u, 1);
}
}
//for(int i = 1; i <= n; i++) cout<<tree[i]<<" ";
}
【luogu P2146 [NOI2015]软件包管理器】 题解的更多相关文章
- 【题解】Luogu P2146 [NOI2015]软件包管理器
题面:https://www.luogu.org/problemnew/lists?name=2146 这道题要用树链剖分,我博客里有对树链剖分的详细介绍 这道题就是树链剖分的模板,详细解释见程序. ...
- 洛谷P2146 [NOI2015]软件包管理器 题解 树链剖分+线段树
题目链接:https://www.luogu.org/problem/P2146 本题涉及算法: 树链剖分: 线段树(区间更新及求和,涉及懒惰标记) 然后对于每次 install x ,需要将 x 到 ...
- Luogu P2146 [NOI2015]软件包管理器 树剖
卸载:把子树清空: 安装:把自己到$1$的链改为$1$ #include<cstdio> #include<iostream> #include<cstring> ...
- 题解 P2146 [NOI2015]软件包管理器
P2146 [NOI2015]软件包管理器 感觉代码比其他题解更简洁qwq 树链剖分模板题 install x:将1~x的路径上的节点全部变成1(安装x需要先安装1~x) uninstall x:将x ...
- 洛谷 P2146 [NOI2015]软件包管理器 解题报告
P2146 [NOI2015]软件包管理器 题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软 ...
- [Luogu 2146] NOI2015 软件包管理器
[Luogu 2146] NOI2015 软件包管理器 树剖好题. 通过对题目的分析发现,这些软件构成一棵树,\(0\) 是树根. 每下载一个软件,需要下载根到这个软件的路径上的所有软件: 每卸载一个 ...
- 洛谷 P2146 [NOI2015]软件包管理器 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例#1: 输出样例#1: 输入样例#2: 输出样例#2: 说明 说明 思路 AC代码 总结 题面 题目链接 P ...
- BZOJ4196:[NOI2015]软件包管理器——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=4196 https://www.luogu.org/problemnew/show/P2146 你决定 ...
- P2146 [NOI2015]软件包管理器
题目链接:https://www.luogu.org/problemnew/show/P2146 题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安 ...
随机推荐
- (Frontend Newbie)JavaScript基础之函数
函数可以说是任何一门编程语言的核心概念.要能熟练掌握JavaScript,对于函数及其相关概念的学习是非常重要的一步.本篇从函数的基本知识.执行环境与作用域.闭包.this关键字等方面简单介绍Java ...
- 案例46-crm练习客户登录
1 login.jsp代码 <%@ page language="java" contentType="text/html; charset=UTF-8" ...
- ActivityGroup和TabActiviy的差异性?
TabActivity功能比较专一,就是做主界面Activity切换用的,所以定制性方面也就限制了许多,而且修改麻烦,不便于维护.ActivityGroup也是用来管理多个Activity的,但是功能 ...
- 腾讯云CDB的AI技术实践:CDBTune
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 作者:邢家树,高级工程师,目前就职于腾讯TEG基础架构部数据库团队.腾讯数据库技术团队维护MySQL内核分支TXSQL,100%兼容原生My ...
- 004 java中的变量
这篇文章为你搞懂三个问题 什么是变量? 如何使用变量? 变量命名有哪些规范? 变量 计算机的内存类似于人的大脑,电脑使用内存来存储计算所需要的数据. 内存像旅馆一样,不同的房间类型对应不同的数据类型, ...
- windows下openssl config failed
老大让我们去学学webpack, 我在一开始就遇到了坎, 调侃自己"webpack从入门到放弃", 在windows下, 报错是"openssl config faile ...
- Java学习第二十天
1:递归(理解) (1)方法定义中调用方法本身的现象 举例:老和尚给小和尚讲故事,我们学编程 (2)递归的注意事项: A:要有出口,否则就是死递归 B:次数不能过多,否则内存溢出 C:构造方法不能递归 ...
- 在 UWP 应用中创建、使用、调试 App Service (应用服务)
在 Windows 10 中微软为 UWP 引入了 App Service (即应用服务)这一新特性用以提供应用间交互功能.提供 App Service 的应用能够接收来自其它应用传入的参数进行处理后 ...
- Csharp:操作存儲過程輸出參數,和返回值
/// <summary> ///塗聚文 存儲過程輸出參數,和返回值 /// 20131030 /// Geovin Du /// </summary> /// <par ...
- 序列化及json&pickle的使用
一.序列化 序列化是指把内存里的数据类型转变成字符串.以使其能存储到硬盘或通过网络传输到远程.——硬盘或网络传输时只能接受bytes. Python中用于序列化的两个模块: json:用于字符串和Py ...