CCPC河南省赛-C|树状数组dfs序上处理子树问题 + 离散化

Posted fisherss

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CCPC河南省赛-C|树状数组dfs序上处理子树问题 + 离散化相关的知识,希望对你有一定的参考价值。

C题地址:大小接近的点对

分析题目:
技术图片

方法一:

在dfs序上,树状数组维护每个数出现的次数;因为在dfs序上根比它的子孙先遍历到(遍历到根时,还没加入遍历孩子)
题目要统计 u是v的祖先时,dfs序就保证了,"在遍历到的结点x是根,而接下来遍历的都是它的子孙",
递归思想,叶节点先计算完,再向父亲更新,父亲再像父亲更新贡献,完事。

总结:dfs序用来处理 根和它子树问题

很清楚的思想:dfs序上作两次查询,1次统计遍历子树前,1次统计遍历子树后的贡献,两者相减就是子树的贡献了

技术图片

方法二:主席树在dfs序的 入时间戳 和 出时间戳上 统计区间和,思路没问题吧。

技术图片

这里先放上方法一的做法,方法二写的代码wa了,但它肯定有被ac的那一天!

#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
",sum[i]);
    return 0;
} 

以上是关于CCPC河南省赛-C|树状数组dfs序上处理子树问题 + 离散化的主要内容,如果未能解决你的问题,请参考以下文章

2021CCPC河南省赛欢度佳节

第一届CCPC河南省赛

「luogu2414」[NOI2011]阿狸的打字机

Codeforces 1076E Vasya and a Tree(树状数组)

luogu SP8093 后缀自动机+树状数组+dfs序

POJ-3321 Apple Tree---树状数组+DFS序