题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1556
题目意思:有 n 个气球从左到右排成一排,编号依次为1,2,3,...,n。给出 n 对 a, b,表示编号为 a ~b 的气球被涂过一次色。n 次之后,问所有气球被上色的次数分别是多少。
典型的树状数组题!这种是:每次修改一个区间,问的是最后每个点被修改的次数。要注意update() 函数对 a 处理 的时候,向上修改的过程中把不必要的区间都加了一遍。例如对a = 2时,update修改了c[2],c[4],c[8],那么还需要对 b+1 进行update,把不必要的被修改区间调整回来,即减去1。
树状数组还是很不熟悉,尤其对于get_sum() 函数。对样例
8
1 1
1 2
1 3
1 4
1 5
1 6
1 7
1 8
0
处理完之后得出以下这个图:
ans: 8 7 6 5 4 3 2 1
update 比较好理解,不再累赘。
get_sum(1) = c[1] = 8; get_sum(2) = c[2] = 7; get_sum(3) = c[3] + c[2] = -1 + 7 = 6
get_sum(4) = c[4] = 5; get_sum(5) = c[5] + c[4] = -1 + 5 =4; get_sum(6) = c[6] + c[4] = -2 + 5 = 3
get_sum(7) = c[7] + c[6] + c[4] = -1 -2 + 5 = 2; get_sum(8) = c[8] = 1
经过手动模拟,对这个求和函数了解了不少 (灵活运用还需要一段时间,继续努力吧[^_^])
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 using namespace std; 6 7 const int maxn = 100000 + 5; 8 int n; 9 int c[maxn]; 10 11 int lowbit(int x) 12 { 13 return x & (-x); 14 } 15 16 void update(int x, int num) 17 { 18 while (x <= n) { 19 c[x] += num; 20 x += lowbit(x); 21 } 22 } 23 24 int get_sum(int x) 25 { 26 int s = 0; 27 while (x > 0) { 28 s += c[x]; 29 x -= lowbit(x); 30 } 31 return s; 32 } 33 34 int main() 35 { 36 #ifndef ONLINE_JUDGE 37 freopen("in.txt", "r", stdin); 38 #endif // ONLINE_JUDGE 39 40 while (scanf("%d", &n) != EOF && n) { 41 memset(c, 0, sizeof(c)); 42 int a, b; 43 for (int i = 0; i < n; i++) { 44 scanf("%d%d", &a, &b); 45 update(a, 1); 46 update(b+1, -1); 47 } 48 for (int i = 1; i <= n; i++) { 49 printf("%d%c", get_sum(i), (i == n ? ' ' : ' ')); 50 } 51 } 52 return 0; 53 }