Description

奈特公司是一个巨大的情报公司,它有着庞大的情报网络。情报网络中共有n名情报员。每名情报员口J-能有
若T名(可能没有)下线,除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
 
题解:
  这个题目,树链剖分是十分显然的,但是怎么进行修改呢?
  首先我们可以知道,我们把询问按照i-c来排序,i-c-1就是对答案可以做出贡献的最大修改操作的标号,然后我们把修改询问按标号来排序,那么对于一个询问i,我们考虑加入修改操作,如果当前的修改操作的标号x<i-c,那么显然他可以对答案做出贡献,我们就执行修改,直到x>i-c,为止,再进行查询操作,因为我们的修改操作的指针是单调的,不需要将加过的点改回去,所以复杂度是对的。
  但为什么能保证是正确的呢?显然C是大于0的,所以第i个决策所要求的修改操作的标号一定是在他之前的,就不可能将其后面的操作加入,所以正确。
  这个离线还是比较巧妙!
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#define MAXN 201000
using namespace std;
struct tree{
int sum1,sum2,l,r;
}tr[MAXN*];
struct que{
int id,x,y,c,t,ans1,ans2;
}q1[MAXN];
struct que2{
int id,x,d;
}q2[MAXN];
struct edge{
int first,next,to;
}a[MAXN*];
int dep[MAXN],fa[MAXN],size[MAXN],son[MAXN],top[MAXN],pos[MAXN];
int n,q,num=,num2=,cnt=,cnt2=; void addedge(int from,int to){
a[++num].to=to;
a[num].next=a[from].first;
a[from].first=num;
} void dfs1(int now,int f){
fa[now]=f,size[now]=,dep[now]=dep[f]+;
for(int i=a[now].first;i;i=a[i].next){
int to=a[i].to;
if(to==f) continue;
dfs1(to,now);
size[now]+=size[to];
if(size[son[now]]<size[to]) son[now]=to;
}
} void dfs2(int now,int tp){
top[now]=tp,pos[now]=++num2;
if(son[now]) dfs2(son[now],tp);
for(int i=a[now].first;i;i=a[i].next){
int to=a[i].to;
if(to==fa[now]||to==son[now]) continue;
dfs2(to,to);
}
} bool cmp(que x,que y){if(x.t!=y.t)return x.t<y.t;else return x.id<y.id;}
bool cmp2(que2 x,que2 y){return x.id<y.id;}
bool cmp3(que x,que y){return x.id<y.id;} int query(int xv,int L,int R,int l,int r,int hh){
if(l==L&&r==R){
if(hh==) return tr[xv].sum1;
else return tr[xv].sum2;
}
int mid=(L+R)/;
if(r<=mid) return query(xv*,L,mid,l,r,hh);
else if(l>mid) return query(xv*+,mid+,R,l,r,hh);
else return query(xv*,L,mid,l,mid,hh)+query(xv*+,mid+,R,mid+,r,hh);
} void getans(int hh){
int x=q1[hh].x,y=q1[hh].y,topx=top[x],topy=top[y],ans1=,ans2=;
while(topx!=topy){
if(dep[topx]<dep[topy]) swap(topx,topy),swap(x,y);
ans1+=query(,,num2,pos[topx],pos[x],);
ans2+=query(,,num2,pos[topx],pos[x],);
x=fa[topx];
topx=top[x];
}
if(dep[x]<dep[y]) swap(x,y);
ans1+=query(,,num2,pos[y],pos[x],);
ans2+=query(,,num2,pos[y],pos[x],);
q1[hh].ans1=ans1,q1[hh].ans2=ans2;
} void change(int xv,int L,int R,int id,int hh){
if(L==R&&L==id){
if(hh==) tr[xv].sum1=;
else tr[xv].sum2=;
return;
}
int mid=(L+R)/;
if(id<=mid) change(xv*,L,mid,id,hh);
else change(xv*+,mid+,R,id,hh);
tr[xv].sum1=tr[xv*].sum1+tr[xv*+].sum1;
tr[xv].sum2=tr[xv*].sum2+tr[xv*+].sum2;
} int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++){
int x;scanf("%d",&x);
addedge(i,x),addedge(x,i);
}
dfs1(,);dfs2(,);
scanf("%d",&q);
for(int i=;i<=q;i++){
int id;scanf("%d",&id);
if(id==){
int x,y,c;scanf("%d%d%d",&x,&y,&c);cnt++;
q1[cnt].x=x,q1[cnt].y=y,q1[cnt].c=c,q1[cnt].t=i-c,q1[cnt].id=i;
}
else{
int x;scanf("%d",&x);
q2[++cnt2].x=x;q2[cnt2].id=i;
}
}
sort(q1+,q1+cnt+,cmp);
sort(q2+,q2+cnt2+,cmp2);
int now=;
for(int i=;i<=n;i++) change(,,num2,pos[i],);
for(int i=;i<=cnt;i++){
while(now<=cnt2&&q2[now].id<q1[i].t){
change(,,num2,pos[q2[now].x],);now++;
}
getans(i);
}
sort(q1+,q1+cnt+,cmp3);
for(int i=;i<=cnt;i++){
printf("%d %d\n",q1[i].ans2,q1[i].ans1);
}
return ;
}

BZOJ [Scoi2015]情报传递的更多相关文章

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

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

  2. BZOJ_4448_[Scoi2015]情报传递_主席树

    BZOJ_4448_[Scoi2015]情报传递_主席树 Description 奈特公司是一个巨大的情报公司,它有着庞大的情报网络.情报网络中共有n名情报员.每名情报员口J-能有 若T名(可能没有) ...

  3. 【BZOJ4448】[Scoi2015]情报传递 主席树+LCA

    [BZOJ4448][Scoi2015]情报传递 Description 奈特公司是一个巨大的情报公司,它有着庞大的情报网络.情报网络中共有n名情报员.每名情报员能有若干名(可能没有)下线,除1名大头 ...

  4. [SCOI2015]情报传递[树剖+主席树]

    [SCOI2015]情报传递 题意大概就是 使得在 \(i\) 时刻加入一个情报员帮您传情报 然后询问 \(x,y,c\) 指 \(x\)到\(y\)多少个人有风险-(大于c)的都有风险-每天风险值+ ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 我的MarkDown入门

    目录 0.前言 1.软件准备 2.基本语法 2.1斜体&加粗 2.2分级标题 2.3分割线 2.4超链接 2.5列表 2.6引用 2.7插入代码 2.8插入图像 2.9插入表格 2.10目录 ...

  2. TypeScript中是使用强类型函数作为参数

    class Foo { save(callback: (n: number) => any) : void { callback(42) } multipleCallbacks(firstCal ...

  3. FreeSql (十六)分页查询

    IFreeSql fsql = new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.MySql, "Data ...

  4. STL 补档

    STL 补档 1.vector 作用:它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据. vector在C++标准模板库中的部分内容,它是 ...

  5. C++11部分特性

    初识C++的时候,觉得会个STL就差不多了,后来发现了C++11这个东西,以及C++14,C++17QAQ,看了一下,好高深不学,emmmm真香= = 这里就只讲一下对ACM写代码有很高帮助的部分特性 ...

  6. 个人网站(sysoft.net.cn)被k,公司名都搜索不出来了,怎么办?

    今年上班后,好2019年3月初,上班后(年前大病一场 ,两个月没维护网站),发现公司网站所有收录都掉了,搜索公司名都不不到了,宝宝真是惊呆了.   有些人说是百度出了故障,有人说是百度算法.   说句 ...

  7. request的请求转发

    1.请求转发和重定向的区别 重定向: 请求转发: 可以看出,请求转发只需要发起一次请求,与重定向不同,请求转发发生在服务器内部.请求转发后浏览器的地址不会改变. 2.request请求转发 需要建立两 ...

  8. Vue学习之如何进行调试

    调试方法 vue调式方法,浏览器检查元素进入到console 1.console.log() 2.alert('sd') 3.debugger //程序会运行到这里停止 ![](https://img ...

  9. 解决mysql不能在查询A表的同时,更新A表的问题

    方法: 运用中间表 UPDATE 表名 SET 字段名 = '' WHERE id in (SELECT a.id FROM (SELECT id FROM 表名 WHERE ISNULL(字段名)) ...

  10. Hadoop核心组件之HDFS

    HDFS:分布式文件系统 一句话总结 一个文件先被拆分为多个Block块(会有Block-ID:方便读取数据),以及每个Block是有几个副本的形式存储 1个文件会被拆分成多个Block blocks ...