Written with StackEdit.

Description

奈特公司是一个巨大的情报公司,它有着庞大的情报网络。情报网络中共有\(n\)名情报员。每名情报员能有若干名(可能没有)下线,除\(1\)名大头目外其余\(n-1\)名情报员有且仅有\(1\)名上线。奈特公司纪律森严,每名情报员只能与自己的上、下线联系,同时,情报网络中任意两名情报员一定能够通过情报网络传递情报。

奈特公司每天会派发以下两种任务中的一个任务:

1.搜集情报:指派\(T\)号情报员搜集情报

2.传递情报:将一条情报从\(X\)号情报员传递给\(Y\)号情报员

情报员最初处于潜伏阶段,他们是相对安全的,我们认为此时所有情报员的危险值为\(0\);

一旦某个情报员开始搜集情报,他的危险值就会持续增加,每天增加1点危险值(开始搜集情报的当天危险值仍为\(0\),第\(2\)天危险值为\(1\),第\(3\)天危险值为\(2\),以此类推)。传递情报并不会使情报员的危险值增加。

为了保证传递情报的过程相对安全,每条情报都有一个风险控制值\(C\)。奈特公司认为,参与传递这条情报的所有情报员中,危险值大于\(C\)的情报员将对该条情报构成威胁。

现在,奈特公司希望知道,对于每个传递情报任务,参与传递的情报员有多少个,其中对该条情报构成威胁的情报员有多少个。

Input

第\(1\)行包含\(1\)个正整数\(n\),表示情报员个数。

笫\(2\)行包含\(n\)个非负整数,其中第\(i\)个整数\(Pi\)表示\(i\)号情报员上线的编号。特别地,若\(P_i=0\),表示\(i\)号情报员是大头目。

第\(3\)行包含\(1\)个正整数\(q\),表示奈特公司将派发\(q\)个任务(每天一个)。

随后\(q\)行,依次描述\(q\)个任务。

每行首先有\(1\)个正整数\(k\)。若\(k=1\),表示任务是传递情报,随后有3个正整数\(X_i、Y_i、C_i\),依次表示传递情报的起点、终点和风险控制值;

若\(k=2\),表示任务是搜集情报,随后有\(1\)个正整数\(T_i\),表示搜集情报的情报员编号。

Output

对于每个传递情报任务输出一行,应包含两个整数,分别是参与传递情报的情报员个数和对该条情报构成威胁的情报员个数。

输出的行数应等于传递情报任务的个数,每行仅包含两个整数,用一个空格隔开。输出不应包含多余的空行和空格。

Sample Input

7

0 1 1 2 2 3 3

6

1 4 7 0

2 1

2 4

2 7

1 4 7 1

1 4 7 3

Sample Output

5 0

5 2

5 1

HINT

\(n< = 2×10^5,Q< = 2×105,0< P_i,C_i< = N, 1< = T_i,X_i,Y_i< = n.\)

Solution

  • 第一问求\(LCA\),第二问对树上路径查询,显然先来一个树链剖分.
  • 考虑如何解决第二问.情报员第一次被指派时,给一个当前时间\(i\)作为权值.
  • 那么每次询问,若询问的时间为\(i\),则只需要询问路径上权值\(\leq i-C-1\)的点有多少个.使用树链剖分后,即为询问区间上某个数的排名.
  • 那么只需要维护一颗树套树即可(在线比较方便),外层可以选用树状数组,因为这里询问个数是可以直接用前缀和相减的.
#include<bits/stdc++.h>
const int inf=1e9;
using namespace std;
typedef long long LoveLive;
inline int read()
{
int out=0,fh=1;
char jp=getchar();
while ((jp>'9'||jp<'0')&&jp!='-')
jp=getchar();
if (jp=='-')
{
fh=-1;
jp=getchar();
}
while (jp>='0'&&jp<='9')
{
out=out*10+jp-'0';
jp=getchar();
}
return out*fh;
}
const int MAXN=2e5+10;
int idx=0;
int x,y,z,r,p,q;
struct node{
int lson,rson,key,siz,weight;
}treap[MAXN*20];
struct FhqTreap{
int root;
FhqTreap()
{
treap[0].lson=treap[0].rson=treap[0].siz=0;
root=0;
}
#define rt treap[o]
#define ls treap[treap[o].lson]
#define rs treap[treap[o].rson]
inline int newnode(int key)
{
int o=++idx;
rt.lson=rt.rson=0;
rt.key=key;
rt.siz=1;
rt.weight=rand();
return o;
}
void pushup(int o)
{
rt.siz=ls.siz+rs.siz+1;
}
int BuildTree(int l,int r)
{
if(l>r)
return 0;
int mid=(l+r)>>1;
int o=newnode(inf);
rt.lson=BuildTree(l,mid-1);
rt.rson=BuildTree(mid+1,r);
pushup(o);
return o;
}
void split(int &x,int &y,int val,int o)
{
if(!o)
x=y=0;
else
{
if(val<rt.key)
{
y=o;
split(x,rt.lson,val,rt.lson);
}
else
{
x=o;
split(rt.rson,y,val,rt.rson);
}
pushup(o);
}
}
int merge(int X,int Y)
{
if(X==0 || Y==0)
return X+Y;
if(treap[X].weight<treap[Y].weight)
{
treap[X].rson=merge(treap[X].rson,Y);
pushup(X);
return X;
}
else
{
treap[Y].lson=merge(X,treap[Y].lson);
pushup(Y);
return Y;
}
}
void ins(int val)
{
int o=newnode(val);
root=merge(root,o);
}
int count(int lim)//<=lim
{
split(x,y,lim,root);
int res=treap[x].siz;
root=merge(x,y);
return res;
}
};
int n,m;
FhqTreap bit[MAXN];
#define lowbit(X) X&(-X)
void add(int X,int c)
{
for(;X<=n+1;X+=lowbit(X))
{
bit[X].ins(c);
}
}
int sum(int X,int lim)
{
int res=0;
for(;X;X-=lowbit(X))
res+=bit[X].count(lim);
return res;
}
int cnt=0,head[MAXN];
int nx[MAXN<<1],to[MAXN<<1];
inline void addedge(int u,int v)
{
++cnt;
to[cnt]=v;
nx[cnt]=head[u];
head[u]=cnt;
}
void insedge(int u,int v)
{
addedge(u,v);
addedge(v,u);
}
int dfn[MAXN],tid[MAXN],dfnidx=0;
int fa[MAXN],top[MAXN],dep[MAXN];
int siz[MAXN],mxson[MAXN];
void dfs1(int u,int Fa)
{
siz[u]=1;
fa[u]=Fa;
dep[u]=dep[Fa]+1;
for(int i=head[u];i;i=nx[i])
{
int v=to[i];
if(v!=Fa)
{
dfs1(v,u);
if(siz[v]>siz[mxson[u]])
mxson[u]=v;
siz[u]+=siz[v];
}
}
}
void dfs2(int u,int tp)
{
dfn[u]=++dfnidx;
tid[dfnidx]=u;
top[u]=tp;
if(mxson[u])
dfs2(mxson[u],tp);
for(int i=head[u];i;i=nx[i])
{
int v=to[i];
if(v!=fa[u] && v!=mxson[u])
dfs2(v,v);
}
}
int LCA(int u,int v)
{
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])
swap(u,v);
u=fa[top[u]];
}
return dep[u]<dep[v]?u:v;
}
int query(int u,int v,int lim)
{
int res=0;
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])
swap(u,v);
res+=sum(dfn[u],lim)-sum(dfn[top[u]]-1,lim);
u=fa[top[u]];
}
if(dep[u]<dep[v])
swap(u,v);
res+=sum(dfn[u],lim)-sum(dfn[v]-1,lim);
return res;
}
int vis[MAXN];
int main()
{
srand(time(NULL));
n=read();
int root;
for(int i=1;i<=n;++i)
{
int p=read();
if(!p)
root=i;
else
insedge(i,p);
}
dfs1(root,0);
dfs2(root,root);
m=read();
for(int i=1;i<=m;++i)
{
int op=read();
if(op==1)
{
int u=read(),v=read(),c=read();
int lca=LCA(u,v);
int ans1=dep[u]+dep[v]-2*dep[lca]+1;
int ans2=query(u,v,i-c-1);
printf("%d %d\n",ans1,ans2);
}
else
{
int t=read();
if(!vis[t])
{
add(dfn[t],i);
vis[t]=1;
}
}
}
return 0;
}

bzoj 4448 情报传递的更多相关文章

  1. BZOJ 4448: [Scoi2015]情报传递 树链剖分 主席树

    4448: [Scoi2015]情报传递 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4448 Description 奈特公司是一个巨 ...

  2. bzoj 4448 [Scoi2015]情报传递(主席树,LCA)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4448 [题意] 给定一颗树,询问一条路径上权值小于t-c的点数. [思路] 将一个2查 ...

  3. bzoj 4448 [Scoi2015]情报传递 (树链剖分+主席树)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4448 题面: Description 奈特公司是一个巨大的情报公司,它有着庞大的情报网络 ...

  4. bzoj 4448: [Scoi2015]情报传递

    Description 奈特公司是一个巨大的情报公司,它有着庞大的情报网络.情报网络中共有n名情报员.每名情报员口J-能有 若T名(可能没有)下线,除1名大头日外其余n-1名情报员有且仅有1名上线.奈 ...

  5. 洛谷 4216 BZOJ 4448 [SCOI2015]情报传递

    [题解] 每个情报员的危险值val[i]应该是一个分段函数,前面一段是平行于x轴的横线,后面一段是一次函数.我们可以用fx(t)=t-b[x]表示这个一次函数.每次询问一条链上fx(t)大于c的点的个 ...

  6. bzoj 4448 [Scoi2015]情报传递 主席树

    比较套路的题目. 可以发现难点在于某个点的权值动态修改 且我们要维护树上一条路径上的点权>x的个数. 每个点都在动态修改 这意味着我们的只能暴力的去查每个点. 考虑将所有可以动态修改的点变成静态 ...

  7. dfs序+主席树 或者 树链剖分+主席树(没写) 或者 线段树套线段树 或者 线段树套splay 或者 线段树套树状数组 bzoj 4448

    4448: [Scoi2015]情报传递 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 588  Solved: 308[Submit][Status ...

  8. BZOJ 4448 主席树+树链剖分(在线)

    为什么题解都是离线的-- (抄都没法抄) 搞一棵主席树 1 操作 新树上的当前节点设成1 2 操作 查max(i-xx-1,0)那棵树上这条路径上有多少个点是1 让你找经过了多少个点 查的时候用dee ...

  9. BZOJ [Scoi2015]情报传递

    Description 奈特公司是一个巨大的情报公司,它有着庞大的情报网络.情报网络中共有n名情报员.每名情报员口J-能有 若T名(可能没有)下线,除1名大头日外其余n-1名情报员有且仅有1名上线.奈 ...

随机推荐

  1. 2018-2019-2 20165114《网络对抗技术》Exp4 恶意代码分析

    Exp4 恶意代码分析 目录 一.实验目标 (1)监控你自己系统的运行状态,看有没有可疑的程序在运行. (2)分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使用原生指令或sys ...

  2. 判断当前html是否在微信中打开

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...

  3. Spring中Bean管理的常用注解

    在Spring中,主要用于管理bean的注解分为四大类:1.用于创建对象.2.用于给对象的属性注入值.3.用于改变作用的范围.4.用于定义生命周期.这几个在开发中经常接触到,也可以说每天都会遇见.其中 ...

  4. quartz(5)--作业管理和存储

    作业一旦被调度,调度器需要记住并且跟踪作业和它们的执行次数.如果你的作业是30分钟后或每30秒调用,这不是很有用.事实上,作业执行需要非常准确和即时调用在被调度作业上的execute()方法.Quar ...

  5. Hibernate -- 操作持久化对象

    知识点2: session概述 Session 接口是 Hibernate 向应用程序提供的操纵对数据库的最主要的接口,它提供了基本的保存,更新, 删除和加载Java对象的方法. 知识点3:理解ses ...

  6. PlusOne

    问题描述:一个数组每一位代表一个数字的每一位.数字高位在数组的低位.求数字加1后得到新数组. 算法分析:要从数组的高位到低位进行遍历. public class PlusOne { public in ...

  7. Search for a range, 在一个可能有重复元素的有序序列里找到指定元素的起始和结束位置

    问题描述:给定一个有序序列,找到指定元素的起始和结束位置.例如:1234555,5,起始4结束6 算法分析:其实就是一个二分查找的利用.但是特殊就在不是找到某个元素,而是找到下标.也就是在nums[m ...

  8. 因磁盘爆满而导致NameNode HA无法启动

    场景回顾: 测试集群节点分配:35,36是namenode且开启HA,37,38,39即作为datanode,又作为journalnode. 某时间 38节点磁盘爆满,集群中hdfs及依赖的服务全部宕 ...

  9. RedHat 6.4企业版利用iso镜像做本地yum源

    修改文章:http://linux.cn/article-1017-1.html 而RedHat的yum则需要注册付费才能使用,如果不这样则有两种解决方案 1. 利用iso镜像做本地yum源 2. 利 ...

  10. MarkDown中锚的使用

    经常使用Markdown配合Mou编辑器来些点总结和文档,但是其中需要前后引用或链接时markdown木有提供直接的方式.当然,Markdown支持嵌入式HTML语法,so..实现起来也没啥问题. 具 ...