当前位置: 代码迷 >> 综合 >> HDU1556 color the ball(树状数组)向下查询,向上统计
  详细解决方案

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

热度:25   发布时间:2023-12-06 20:13:15.0

解题思路:

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

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



  相关解决方案