CCPC 허난 인종 -C | 펜윅 나무에 처리하는 서브 트리 문제는 개별 시퀀스 +를 DFS

문제 C 주소 : 점의 크기에 가까운

분석 제목 :

방법 1 :

DFS 순서, 펜윅 트리 유지 관리 시간마다 번호가 나타납니다에, 순서에 통과 할 자손보다 루트를 DFS 때문에 (루트에 통과하는 경우, 통과 아이를 가입하지)
유 V 일 때 통계 조상 대상 , DFS는 "노드 X 루트, 다음 통과 자손은이다에 횡단"확보하기 위해
재귀 적 사고, 계산, 아버지 업데이트의 리프 노드 일단 그의 아버지처럼, 다시 그의 아버지가 기여 업데이 트를 , 빈.

요약 : IT와 서브 트리의 루트 문제를 처리하기 위해 DFS 위해

아주 명확한 아이디어 : 기본 통계 하위 트리를 통과하기 전에, DFS 순서에 두 개의 쿼리를 만들 수는 기본 통계 하위 트리 탐색의 기여는 두 가지가 빼기 그 하위 트리의 기여

방법 2 : 통계 간격 및 시간 스탬프에 순서와 타임 스탬프 DFS의 나무 회장, 문제를 생각하지 않습니다.

여기에 접근하는 방법을 넣어, 방법이 코드 웨스턴 오스트 레일 리아를 썼다, 그러나 확실히 일 것으로 교류되었습니다!

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 1e5+10;
ll a[maxn];
ll sum[maxn],c[maxn];
const int INF = 0x3f3f3f3f;
vector<int> vec;
vector<ll> g[maxn];
int  n;
ll k;

//树状数组 
int lowbit(int x){
    return x & -x;
}

void add(int x, int v){
    while (x < maxn){
        c[x] += v;
        x += lowbit(x);
    }
}

int query(int x){
    if (x >= maxn)
        return 0;
    int res = 0;
    while (x)
        res += c[x], x -= lowbit(x);
    return res;
}

int rangeQuery(int l, int r){
    return query(r) - query(l - 1);
}

//dfs序上 查询和更新树状数组 
void dfs(int x){
    int l = lower_bound(vec.begin(),vec.end(),a[x] - k ) - vec.begin(); //找到左边界下标() 
    int r = lower_bound(vec.begin(),vec.end(),a[x] + k ) - vec.begin(); //找到右边界下标() 
    if(r >= vec.size() || vec[r] > a[x] + k) --r; //右边界没找到 规定为vec容器的最后一个值 
    ll cnt1 = rangeQuery(l,r); //先求出 dfs子树前的贡献 
    add(lower_bound(vec.begin(),vec.end(),a[x]) - vec.begin(),1); //出现次数+1 
    for(int v : g[x]){
        dfs(v);
        sum[x] += sum[v]; //加上孩子们的贡献 
    }  
    ll cnt2 = rangeQuery(l,r); //再求出 dfs子树后的贡献 
    sum[x] += cnt2 - cnt1; //两者相减的差 就是子树的贡献了 
}

int main(){
    scanf("%d %lld",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        vec.push_back(a[i]);
    }
    //离散化 
    vec.push_back(-INF);
    sort(vec.begin(),vec.end());
    vec.erase(unique(vec.begin(),vec.end()),vec.end());
    for(int i=1;i<=n-1;i++){
        ll fa;
        scanf("%lld",&fa);
        g[fa].push_back(i+1);
    }
    dfs(1);
    for(int i=1;i<=n;i++) printf("%lld\n",sum[i]);
    return 0;
} 

추천

출처www.cnblogs.com/fisherss/p/12233162.html