CCPC Henan race -C | processing sub-tree problem on Fenwick tree dfs discrete sequence +

Problem C Address: size close to a point

Analysis Title:

method one:

On dfs order, Fenwick tree maintenance times each number appears; because in order dfs root than its offspring to traverse to (when traversing to the root, not joined traversing children)
subject to statistical ancestors when u is v , dfs order to ensure the "traversing to the node x is the root, and the next traversal are its descendants,"
recursive thinking, leaf node first end of the calculation, the father update again, like his father and then his father contributed update , bin.

Summary: dfs order to process it and the subtree root problem

Very clear idea: to make two queries on dfs sequence, before traversing the primary statistical sub-tree, the contribution of the primary statistical sub-tree traversal, subtract the two is that the contribution of the sub-tree

Method Two: Chairman of the tree in the sequence and timestamp dfs on a statistical interval and time stamp, thinking no problem.

Here to put a method of approach, method two wrote the code wa, but it certainly has been ac that day!

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

Guess you like

Origin www.cnblogs.com/fisherss/p/12233162.html