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. Python面试题之Python和Java中Super方法的区别

    python 的 super 是一个函数,需要两个参数,第一个参数是类,第二个参数是实例,返回值是一个类对象. 其意义是:站在参数2这个实例的角度看去, 参数1这个类的‘父亲’是谁,把‘父亲’返回. ...

  2. 插入算法分别从C,java,python三种语言进行书写

    真正学懂计算机的人(不只是“编程匠”)都对数学有相当的造诣,既能用科学家的严谨思维来求证,也能用工程师的务实手段来解决问题——而这种思维和手段的最佳演绎就是“算法”. 作为一个初级编程人员或者说是一个 ...

  3. Linux(CentOS)中常用软件安装,使用及异常——XManager, 中文支持,JDK

    XManager图形化界面远程连接 采用Xshell的方式可以不用在CentOS系统中配置即可以相连,主要原理就是SSH连接的方式,但是XManager图形化界面远程连接是需要修改CentOS系统的. ...

  4. Axis2创建WebService实例

      一.Axis2的下载和安装 1.可从http://ws.apache.org/axis2/ 下载Axis2的最新版本:      可以下载如下两个zip包:      axis2-1.5.4-bi ...

  5. E - Water Distribution

    E - Water Distribution 题目大意: 有\(N\)座城市,给定这\(N\)座城市的坐标和初始的水量\(x_i,y_i,a_i\),在两个城市之间运水的花费是两个城市的欧几里得距离. ...

  6. 将 sql 数据库 编码 改成 Chinese_PRC_CS_AS

    use master go ) drop procedure [dbo].[p_killspid] GO create proc p_killspid ) --要关闭进程的数据库名 as ) ) de ...

  7. Apache HTTP Server——官网下载

    Windows版 Apache 2.4.x OpenSSL 1.0.2 VC14  ——Apache 2.4.34 x64(注:x64就是64位,x86就是32位) https://www.apach ...

  8. 报错HTTP Status 500 - Unable to instantiate Action

    报错如下: HTTP Status 500 - Unable to instantiate Action, visitAction, defined for 'visit_toAddPage' in ...

  9. python中多线程,多进程,队列笔记(一)

    threading简介:If you want your application to make better use of the computational resources of multi- ...

  10. Codeforces Round #299 (Div. 2)D. Tavas and Malekas

    KMP,先预处理按每个节点标记,扫一遍更新每个匹配位置,最后kmp判断是否有重合而且不相同的地方 注意处理细节,很容易runtime error #include<map> #includ ...