HDOJ1556(树状数组)
题目:
Problem Description
N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色。但是N次以后lele已经忘记了第I个气球已经涂过几次颜色了,你能帮他算出每个气球被涂过几次颜色吗?
Input
每个测试实例第一行为一个整数N,(N <= 100000).接下来的N行,每行包括2个整数a b(1 <= a <= b <= N)。
当N = 0,输入结束。
当N = 0,输入结束。
Output
每个测试实例输出一行,包括N个整数,第I个数代表第I个气球总共被涂色的次数。
Sample Input
3 1 1 2 2 3 3 3 1 1 1 2 1 3 0
Sample Output
1 1 1 3 2 1
分析:区间更新及单点求值问题用树状数组。此时query(i)代表原序列中第i个元素的值的变化量。
代码:
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; #define MAXN 100005 int n, tree[MAXN]; int lowbit(int i) { return i&(-i); } void update(int i, int x) { while (i <= n) { tree[i] += x; i = i + lowbit(i); } } int query(int n) { int sum = 0; while (n > 0) { sum += tree[n]; n = n - lowbit(n); } return sum; } int main() { while (scanf("%d", &n) != EOF&&n) { memset(tree, 0, sizeof(tree)); for (int i = 0; i < n; i++) { int a, b; scanf("%d%d", &a, &b); update(a, 1);//a以后元素+1 update(b + 1, -1);//b以后元素-1 } for (int i = 1; i < n; i++) printf("%d ", query(i)); printf("%d\n", query(n)); } return 0; }