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

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



离线,求出每个点开始搜集情报的最早的时间。

然后询问相当于查询有多少个点,满足位置和时间两个条件。

于是用主席树数一下点即可。

主席树维护根到路径的信息。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 200050
int head[N],to[N<<1],nxt[N<<1],cnt,dfn[N],dep[N],fa[N],root[N],ls[N*30],rs[N*30],t[N*30],tot;
int f[N][20],rt,n,m;
struct A {
    int opt,x,y,z;
}a[N];
inline void add(int u,int v) {
    to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
}
void insert(int &y,int x,int l,int r,int v) {
    y=++tot; t[y]=t[x]+1;
    if(l==r) return ;
    int mid=(l+r)>>1;
    if(v<=mid) rs[y]=rs[x],insert(ls[y],ls[x],l,mid,v);
    else ls[y]=ls[x],insert(rs[y],rs[x],mid+1,r,v);
}
void dfs(int x,int y) {
    int i;
    f[x][0]=y;
    if(dfn[x]) insert(root[x],root[y],1,m,dfn[x]);
    else root[x]=root[y];
    dep[x]=dep[y]+1;
    for(i=head[x];i;i=nxt[i]) {
        if(to[i]!=y) {
            dfs(to[i],x);
        }
    }
}
int lca(int x,int y) {
    int i;
    if(dep[x]<dep[y]) swap(x,y);
    for(i=18;i>=0;i--) {
        if(f[x][i]&&dep[f[x][i]]>=dep[y]) x=f[x][i];
    }
    if(x==y) return x;
    for(i=18;i>=0;i--) {
        if(f[x][i]!=f[y][i]) {
            x=f[x][i]; y=f[y][i];
        }
    }
    return f[x][0];
}
int query(int x,int y,int z,int w,int l,int r,int v) {
    if(l==r) return t[x]+t[y]-t[z]-t[w];
    int sizls=t[ls[x]]+t[ls[y]]-t[ls[z]]-t[ls[w]],mid=(l+r)>>1;
    if(v<=mid) return query(ls[x],ls[y],ls[z],ls[w],l,mid,v);
    else return query(rs[x],rs[y],rs[z],rs[w],mid+1,r,v)+sizls;
}
int main() {
    scanf("%d",&n);
    int i,x,j;
    for(i=1;i<=n;i++) {
        scanf("%d",&x);
        if(x) {
            add(x,i); add(i,x);
        }
    }
    scanf("%d",&m);
    for(i=1;i<=m;i++) {
        scanf("%d",&a[i].opt);
        if(a[i].opt==1) {
            scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
        }else {
            scanf("%d",&x); if(!dfn[x]) dfn[x]=i;
        }
    }
    dfs(1,0);
    for(j=1;(1<<j)<=n;j++) {
        for(i=1;i<=n;i++) {
            f[i][j]=f[f[i][j-1]][j-1];
        }
    }
    for(i=1;i<=m;i++) {
        if(a[i].opt==1) {
            int l=lca(a[i].x,a[i].y);
            int p=f[l][0];
            printf("%d ",dep[a[i].x]+dep[a[i].y]-2*dep[l]+1);
            if(i-a[i].z<=0) {
                printf("0\n");continue;
            }
            printf("%d\n",query(root[a[i].x],root[a[i].y],root[l],root[p],1,m,i-a[i].z-1));
        }
    }
}

原文地址:https://www.cnblogs.com/suika/p/8967147.html

时间: 2024-10-07 20:54:09

BZOJ_4448_[Scoi2015]情报传递_主席树的相关文章

BZOJ_3772_精神污染_主席树

Description 兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是集经济和文化于一体的一大地区,是日本西部门户,海陆空交通设施发达.濑户内海沿岸气候温暖,多晴天,有日本少见的贸易良港神户港所在的神户市和曾是豪族城邑“城下町”的姬路市等大城市,还有以疗养地而闻名的六甲山地等. 兵库县官方也大力发展旅游,为了方便,他们在县内的N个旅游景点上建立了n-1条观光道,构成了一棵图论中的树.同时他们推出了

BZOJ_3514_Codechef MARCH14 GERALD07加强版_主席树+LCT

Description N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. Input 第一行四个整数N.M.K.type,代表点数.边数.询问数以及询问是否加密. 接下来M行,代表图中的每条边. 接下来K行,每行两个整数L.R代表一组询问.对于type=0的测试点,读入的L和R即为询问的L.R:对于type=1的测试点,每组询问的L.R应为L xor lastans和R xor lastans. Output K行每行一个整数代表该组询问的联通块个数. Sample

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

[BZOJ4448][Scoi2015]情报传递 Description 奈特公司是一个巨大的情报公司,它有着庞大的情报网络.情报网络中共有n名情报员.每名情报员能有若干名(可能没有)下线,除1名大头日外其余n-1名情报员有且仅有1名上线.奈特公司纪律森严,每名情报员只能与自己的上.下线联系,同时,情报网络中仟意两名情报员一定能够通过情报网络传递情报. 奈特公司每天会派发以下两种任务中的一个任务: 1.搜集情报:指派T号情报员搜集情报 2.传递情报:将一条情报从X号情报员传递给Y号情报员 情报员

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

[SCOI2015]情报传递 题意大概就是 使得在 \(i\) 时刻加入一个情报员帮您传情报 然后询问 \(x,y,c\) 指 \(x\)到\(y\)多少个人有风险-(大于c)的都有风险-每天风险值+1 看起来-不太可做- 每次要整棵树+1复杂度也需要\(log^2\)的树套树吧 但是显然不用啊 查询的时候减掉就可以了- 所以直接树剖上面无脑主席树就可以了啊- #include <bits/stdc++.h> // #define int long long #define rep(a , b

BZOJ_3207_花神的嘲讽计划Ⅰ_哈希+主席树

Description 背景 花神是神,一大癖好就是嘲讽大J,举例如下: “哎你傻不傻的![hqz:大笨J]” “这道题又被J屎过了!!” “J这程序怎么跑这么快!J要逆袭了!” …… 描述 这一天DJ在给吾等众蒟蒻讲题,花神在一边做题无聊,就跑到了一边跟吾等众蒟蒻一起听.以下是部分摘录: 1. “J你在讲什么!” “我在讲XXX!” “哎你傻不傻的!这么麻烦,直接XXX再XXX就好了!” “……” 2. “J你XXX讲过了没?” “……” “那个都不讲你就讲这个了?哎你傻不傻的!” “……”

主席树复习

T1 [CQOI2015]任务查询系统 n个任务,每个有运行的时间段和优先级,询问某一时刻,优先级最小的个任务的优先级之和 初做:  2017.2.4   http://www.cnblogs.com/TheRoadToTheGold/p/6366165.html 好像是做了一晚上来 现在:2017.3.27   14:17——15:56 用了接近2个小时做了一道以前做过的题,还是弱啊~~~~(>_<)~~~~ difference: 主席树维护的东西不同,以前直接存储优先级之和,现在存储的是

BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status][Discuss] Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[LC

BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]

2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 5217  Solved: 1233[Submit][Status][Discuss] Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文. Input 第一

bzoj 2653 middle (主席树+二分)

版权声明:本文为博主原创文章,未经博主允许不得转载. bzoj 2653 题意: 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序列s. 回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数. 其中a<b<c<d. 位置也从0开始标号. 强制在线. 解法: 首先可以想到的是二分答案,再判断是否满足条件 . 对于答案x,我们将原数组中大于等于x的数记1,小于的记为-1,