您的位置:首页 > 其它

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

2016-10-18 21:46 351 查看
解题思路:

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

这样就可以在时间上,大大缩短,查询和统计的时间复杂度都为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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: