1. 程式人生 > >BZOJ_4448_[Scoi2015]情報傳遞_主席樹

BZOJ_4448_[Scoi2015]情報傳遞_主席樹

namespace efi Go put == scan highlight string.h UC

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));
        }
    }
}

BZOJ_4448_[Scoi2015]情報傳遞_主席樹