HDU1556 color the ball(树状数组)向下查询,向上统计

解题思路:

其实这道题可以把每次染色的点抽象为每次涂改的区间,然后对要查询的点所在区间的更新次数进行求和

这样就可以在时间上,大大缩短,查询和统计的时间复杂度都为log(n)

树状数组中的每个节点都代表了一段线段区间,每次更新的时候,根据树状数组的特性可以把b以前包含的所有区间都找出来,然后b以前的区间全部加一次染色次数。然后,再把a以前的区间全部减一次染色次数,这样就修改了树状数组中的[a,b]的区间染色次数,查询每一个点总的染色次数的时候,就可以直接向上统计每个父节点的值,就是包含这个点的所有区间被染色次数,这就是树状数组中向下查询,向上统计的典型应用

Ps:根据个人理解层次的不同,这道题也可以向上查询,向下统计,还可以向下查询,向下统计。

比如这样一组数据:

1

8 8

想想第四个气球是多少次的过程,C[8]被改成了1, C[7]被改成了-1,c[6]被改成了-1, c[4]被改成了-1,那么在查询c[4]的时候会上升(加上)到c[8],就是上面说的包含这个点的所有区间被染色次数。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 100005;
int C[maxn];
void Update(int i, int value)
{
    while(i != 0)
    {
        C[i] += value;
        i -= i & (-i);
    }
}
int getsum(int i)
{
    int s = 0;
    while(i < maxn)
    {
        s += C[i];
        i += i & (-i);
    }
    return s;
}
int main()
{
    int n;
    while(cin >> n && n)
    {
        memset(C, 0, sizeof(C));
        for(int i = 1; i <= n; i++)
        {
            int l, r;
            scanf("%d%d", &l, &r);
            Update(r, 1);
            Update(l-1, -1);
        }
        for(int i = 1; i < n; i++)
            cout << getsum(i) << " ";
        cout << getsum(n) << endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值