【BZOJ4448】[Scoi2015]情报传递

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号情报员上线的编号。特别地,若Pi=0,表示i号情报员是大头目。
第3行包含1个正整数q,表示奈特公司将派发q个任务(每天一个)。
随后q行,依次描述q个任务。每行首先有1个正整数k。若k=1,表示任务是传递情报,随后有3个正整数Xi、Yi、Ci,依次表示传递情报的起点、终点和风险控制值;若k=2,表示任务是搜集情报,随后有1个正整数Ti,表示搜集情报的情报员编号。

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

对于3个传递情报任务,都是经过5名情报员,分别是4号、2号、1号、3号和7号。其中,对于第1个任务,所有情报员(危险值为0)都不对情报构成威胁;对于第2个任务,有2名情报员对情报构成威胁,分别是1号情报员(危险值为3)和4号情报员(危险值为2),7号情报员(危险值为1)并不构成威胁;对于第3个任务,只有1名情报员对情报构成威胁。
n< = 2×10^5,Q< = 2×105,0< Pi,C!< = N, 1< = Ti,Xi,Yi< = n

题解:离线处理+主席树+倍增LCA,没有别的了~

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn=200010;
struct sag
{
int ls,rs,siz;
}s[maxn*30];
int n,m,cnt,root,tot;
int rt[maxn],fa[maxn][20],to[maxn],next[maxn],head[maxn],dep[maxn];
int v[maxn],qa[maxn],qb[maxn],qc[maxn];
int rd()
{
int ret=0; char gc=getchar();
while(gc<'0'||gc>'9') gc=getchar();
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret;
}
void add(int a,int b)
{
to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
void insert(int x,int &y,int l,int r,int pos)
{
if(!pos)
{
y=x;
return ;
}
y=++tot;
if(l==r)
{
s[y].siz++;
return;
}
int mid=l+r>>1;
if(pos<=mid) s[y].rs=s[x].rs,insert(s[x].ls,s[y].ls,l,mid,pos);
else s[y].ls=s[x].ls,insert(s[x].rs,s[y].rs,mid+1,r,pos);
s[y].siz=s[x].siz+1;
}
void dfs(int x)
{
insert(rt[fa[x][0]],rt[x],1,m,v[x]);
for(int i=head[x];i!=-1;i=next[i]) dep[to[i]]=dep[x]+1,dfs(to[i]);
}
int query(int a,int b,int c,int d,int l,int r,int pos)
{
if(pos<=0) return 0;
if(r<=pos) return s[a].siz+s[b].siz-s[c].siz-s[d].siz;
int mid=l+r>>1;
if(pos<=mid) return query(s[a].ls,s[b].ls,s[c].ls,s[d].ls,l,mid,pos);
return s[s[a].ls].siz+s[s[b].ls].siz-s[s[c].ls].siz-s[s[d].ls].siz+query(s[a].rs,s[b].rs,s[c].rs,s[d].rs,mid+1,r,pos);
}
int main()
{
n=rd();
int i,j,a,b,c;
memset(head,-1,sizeof(head));
for(i=1;i<=n;i++)
{
fa[i][0]=rd();
if(!fa[i][0]) root=i;
else add(fa[i][0],i);
}
m=rd();
for(i=1;i<=m;i++)
{
b=rd();
if(b==1) qa[i]=rd(),qb[i]=rd(),qc[i]=i-rd()-1;
else a=rd(),v[a]=i;
}
for(j=1;(1<<j)<n;j++)
for(i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
dep[1]=1,dfs(1);
for(i=1;i<=m;i++)
{
if(qa[i])
{
a=qa[i],b=qb[i];
if(dep[a]<dep[b]) swap(a,b);
for(j=19;j>=0;j--) if(dep[fa[a][j]]>=dep[b]) a=fa[a][j];
if(a!=b)
{
for(j=19;j>=0;j--) if(fa[a][j]!=fa[b][j]) a=fa[a][j],b=fa[b][j];
a=fa[a][0];
}
c=dep[qa[i]]+dep[qb[i]]-2*dep[a]+1;
printf("%d %d\n",c,query(rt[qa[i]],rt[qb[i]],rt[a],rt[fa[a][0]],1,m,qc[i]));
}
}
return 0;
}

【BZOJ4448】[Scoi2015]情报传递 主席树+LCA的更多相关文章

  1. BZOJ4448[Scoi2015]情报传递——主席树+LCA

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

  2. bzoj4448 [Scoi2015]情报传递 主席树+树上差分

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4448 题解 练习一下主席树的基础练习题找回感觉. 对于每一次询问,第一问显然随便做. 第二问的 ...

  3. 【bzoj4448】[Scoi2015]情报传递 主席树

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

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

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

  5. 4448: [Scoi2015]情报传递|主席树|离线操作

    能够把全部的操作离线,然后树链剖分将全部人搜集情报的时间增加到主席树中,查询的时候能够直接查询搜集情报时间≤i−C[i]−1的人的个数 时间复杂度n∗log22n,空间复杂度n∗log2n #incl ...

  6. Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式)

    Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式) 题外话,这是我第40篇随笔,纪念一下.<( ̄︶ ̄)↗[GO!] 题意 是说有棵树,每个节点上 ...

  7. BZOJ4448 SCOI2015情报传递(离线+树链剖分+树状数组)

    即滋磁单点修改,询问路径上小于某数的值有多少个.暴力树剖套个主席树(或者直接树上主席树,似乎就1个log了?感觉不一定比两个log快)即可,然而不太优美. 开始觉得可以cdq,然而就变成log^3了. ...

  8. 洛谷P4216 [SCOI2015]情报传递(树剖+主席树)

    传送门 我们可以进行离线处理,把每一个情报员的权值设为它开始收集情报的时间 那么设询问的时间为$t$,就是问路径上有多少个情报员的权值小于等于$t-c-1$ 这个只要用主席树上树就可以解决了,顺便用树 ...

  9. bzoj4448 SCOI2015 情报传递 message

    传送门bzoj4448 题解 离线之后构建树上主席树,每个点的线段树维护到根路径的信息,不用链剖(我的链剖只是拿来求\(\mathrm{lca}\)的),时空复杂度\(O(n\log{n})\). c ...

随机推荐

  1. Android中的Service组件具体解释

    Service与Activity的差别在于:Service一直在后台执行,他没实用户界面,绝不会到前台来. 一,创建和配置Service 开发Service须要两个步骤:1.继承Service子类,2 ...

  2. Python——标准库 Sys模块

    ---------------------------------------------------------------------------------------------------- ...

  3. STL坑汇总

    1. Q:vector的push_back()方法到底做了些什么? 为什么声明写的是void push_back (const value_type& val); A:的确,乍一看,似乎pus ...

  4. Python中函数参数传递问题【转】

    1. Python passes everything the same way, but calling it "by value" or "by reference& ...

  5. Spring Sleuth和Zipkin跟踪微服务

    原文地址:http://www.cnblogs.com/skyblog/p/6213683.html 随着微服务数量不断增长,需要跟踪一个请求从一个微服务到下一个微服务的传播过程, Spring Cl ...

  6. Android WebView与JavaScript交互实现Web App

    当我们去开发一个基于web的android app时,我们第一须要处理的就是与JavaScript的交互问题.Android须要做的事情就是开放某些特定的接口供web里的JavaScript调用,能够 ...

  7. FPGA+DSP SRIO通信(一)——DSP端参数设置(通道)

    FPGA+DSP SRIO通信(一)——DSP端参数设置(通道) 原创 2017年04月19日 18:56:45 标签: SRIO-C66x 1217 经过漫长的探索之后,博主发现关于TI的板子调试和 ...

  8. python学习之pyenv

    我们经常有这种需求: linux系统中既要有python2.xxx,又要有python3.xxx,甚至更极端的情况是,有多个版本的python3.xxx. 如何实现上述需求呢?更新python的话,费 ...

  9. mysql命令:set sql_log_bin=on/off

    对于数据库的操作,经常需要暂时停止对bin-log日志的写入,那就需要这个命令:set sql_log_bin=on/off 参考:dev.mysql.com/doc/refman/5.5/en/se ...

  10. windows下安装JDK和Tomcat

    一.安装JDK 1.安装 JDK当前最高版本为1.7. 下载并运行JDK 1.7安装程序jdk-7u25-windows-i586.exe,直接安装到C盘(也可以在其它盘,但文件名一定要是英文名),其 ...