您的位置:首页 > 其它

HDU Color the ball (树状数组)

2015-09-01 18:55 344 查看
题目大意:输入一个数N,表示有N个气球,编号为1 , 2 ,…… ,N,然后有N次操作,每次操作输入两个数a , b。表示给编号为[a , b]所在区间的气球染色, 然后依次求出每个气球被染色的次数.

很容易想到用线段树来求解(成段修改区间值,单点查询),也可以用树状数组来写。 不过很有意思的是, 树状数组一般是用于单点修改,查询区间和的问题, 而这个题要求更新区间,查询单点。因此更新的时候左端点+1, 右端点的下一个位置-1,这样子查询点也就变成求前缀和了。

代码

#include <iostream>
#include <cstring>

using namespace std;
const int maxn = 100010;
int c[maxn] , a[maxn] , n;

int lowbit(int x) {return x & (-x);}
void add(int x , int v)
{
while(x <= n) {
c[x] += v;
x += lowbit(x);
}
}
int sum(int x)
{
int rel = 0;
while(x > 0) {
rel += c[x];
x -= lowbit(x);
}
return rel;
}

int main()
{
ios::sync_with_stdio(false);
while(cin >> n && n)
{
memset(c , 0 , sizeof(c));
//更新区间在线段左端点加1,在右端点后面减一,前缀和就是该点的修改次数
for(int i = 1; i <= n; i++) {
int a , b;
cin >> a >> b;
add(a , 1);
add(b + 1 , -1);
}
for(int i = 1; i < n; i++) cout << sum(i) << " ";
cout << sum(n) << endl;
}
return 0;
}


上述处理方式是树状数组的向上更新 , 向下求和。还有一种处理办法是向下更新 , 向上求和。即采用向下更新的方式将左端点前一个位置-1,右端点+1。然后向上求前缀和。

代码

#include <iostream>
#include <cstring>

using namespace std;
const int maxn = 100010;
int a[maxn] , c[maxn] , n;

int lowbit(int x) {return x & (-x);}
void add(int x , int v)
{
while(x > 0) {
c[x] += v;
x -= lowbit(x);
}
}
int sum(int x)
{
int rel = 0;
while(x <= n) {
rel += c[x];
x += lowbit(x);
}
return rel;
}

int main()
{
ios::sync_with_stdio(false);
while(cin >> n && n)
{
memset(c , 0 , sizeof(c));
for(int i = 0; i < n; i++)
{
int a , b;
cin >> a >> b;
add(a - 1 , -1);
add(b , 1);
}
for(int i = 1; i < n; i++) cout << sum(i) << " ";
cout << sum(n) << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  树状数组