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

来源:互联网 发布:网络审计设备 编辑:程序博客网 时间:2024/06/10 16:29

解题思路:

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

这样就可以在时间上,大大缩短,查询和统计的时间复杂度都为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;}



0 0