题目链接: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]软件包管理器】 题解的更多相关文章

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

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

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

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

  3. Luogu P2146 [NOI2015]软件包管理器 树剖

    卸载:把子树清空: 安装:把自己到$1$的链改为$1$ #include<cstdio> #include<iostream> #include<cstring> ...

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

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

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

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

  6. [Luogu 2146] NOI2015 软件包管理器

    [Luogu 2146] NOI2015 软件包管理器 树剖好题. 通过对题目的分析发现,这些软件构成一棵树,\(0\) 是树根. 每下载一个软件,需要下载根到这个软件的路径上的所有软件: 每卸载一个 ...

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

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

  8. BZOJ4196:[NOI2015]软件包管理器——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=4196 https://www.luogu.org/problemnew/show/P2146 你决定 ...

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

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

随机推荐

  1. 2018最新mfc作为上位机接收硬件端USB或串口数据显示成图片 解决串口接收数据丢字节丢包问题

    原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/9490616.html 本文用的是VS2013MFC写串口数据接收: 第一步:首先建立一个MFC ...

  2. TOJ 3176 Challenge from XOR

    Description Mr. AngelClover just learnt XOR on his Computer Class. XOR is a bit arithmetic operator ...

  3. Web请求过程总结

    Web请求过程总结 1.CND架构图 图片来源:深入分析JavaWeb技术内幕(许令波著) 2.发起HTTP请求 发起一个HTTP请求就是浏览器建立socket通信的过程,HttpClient开源的通 ...

  4. React.js 小书 Lesson11 - 配置组件的 props

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson11 转载请注明出处,保留原文链接和作者信息. 组件是相互独立.可复用的单元,一个组件可能在不 ...

  5. core核心模块

    5. core核心模块 核心模块会通过compiler模块提供的调用compiler的功能, 将用户的输入转为VM直接的输入 编译模块用来编译, 而核心模块用来执行 在core.h文件中 // 不需要 ...

  6. JS常用的设计模式(3)-——观察者模式

    观察者模式( 又叫发布者-订阅者模式 )应该是最常用的模式之一. 在很多语言里都得到大量应用. 包括我们平时接触的dom事件. 也是js和dom之间实现的一种观察者模式. div.onclick = ...

  7. Javascript “等于”

    JavaScript支持“=”.“==”和“===”运算符. 我们应当理解这些(赋值.相等.恒等)运算符之间的区别,并在编码过程中小心使用. == equality 等同,用于一般比较,在比较的时候可 ...

  8. asp.net的几种页面传值方式

    1."~/x/xx.aspx?id=" + id string id=Request.Params["id"].ToString(); 2.Response.R ...

  9. HDU 4268 multiset

    http://acm.hust.edu.cn/vjudge/contest/123100#problem/B #include <iostream> #include <string ...

  10. Java开发中代码规范有哪些?

    Java开发中所要遵守的编码规范大体上有如下7点.命名规范.注释规范.缩进排版规范.文件名规范.声明规范.语句规范以及编程规范. 1.命名规范 (1)所有的标示符都只能用ASCⅡ字母(A-Z或a-z) ...