Hdu 4267 树状数组成段更新.cpp

题意:

给出 n 表示有 n 个位置

然后有 一行 n 个数表示初始状态 每个位置的值

然后给出 m 表示有 m 条order

接下来 m 行..

每行的格式有两种..

1 b 表示询问在 b 点的值

2 a b k x 表示在 a 到 b 里面满足 (i-a)%k == 0 的位置上的值都加 x

思路:

感觉是树状数组了

但是 树状数组是单点更新 而题目要求是在a b 内每隔 k 个数更新..

如果用for循环对a b 内每隔 k 个位置的数更新就会很费时间..

所以有一个方法就是 按 k 值 i%k 值还有 i/k+1 值把每隔 k 个位置的值都分组..即按 k 值和 i%k 值建树状数组 

到时候维护其中一棵 树状数组就好了..

 

维护的方法是在c[ k ][a%k][(i-a)/k+1] + 1 在c[ k ][a % k ][ (a/k) + (b-a)/k + 2 ] - 1..

 

关于建成的树状数组..

更新时有55种情况
1,2,3,4,5......
1,3,5,7,9......
2,4,6,8,10....
1,4,7,10,13...
2,5,9,12,15...
3,6,10,13,16...
.
.
.
10,20,30,40,50...

所以用55个树状数组.

Tips:

树状数组的优势是方便动态求值和更新..

可惜树状数组是单点更新

倒是有个方法可以快速成段更新

就是在区间【a, b】内更新+x就在a的位置+x 然后在b+1的位置-x

求某点a的值就是求数组中1~a的和..

可惜这道题还不是成段更新..而是隔开几个数来更新..

所以就可以多建几棵树..然后就可以转换为成段更新了~~

其中每个位置初始值用一个数组保存..在每次询问的时候加上就好..

 

※ 因为输入数据a, b什么的都是从1 开始的..      而最后要求          ***********不懂..到时候问zz问清楚了再写上..

Code:

View Code
 1 #include <stdio.h>
 2 #include <cstring>
 3 #include <iostream>
 4 using namespace std;
 5 
 6 int n;
 7 int c[12][12][50010];
 8 int lowbit(int x)
 9 {
10    return (x)&(-x);
11 }
12 void modify(int i, int j, int pos,int x)
13 {
14     while(pos<=n)
15     {
16         c[i][j][pos]+=x;
17         pos+=lowbit(pos);
18     }
19 }
20 int getSum(int i, int j, int x)
21 {
22       int sum=0;
23       while(x>0)
24       {
25          sum+=c[i][j][x];
26          x-=lowbit(x);
27       }
28       return sum;
29 }
30 
31 int main()
32 {
33     int i, j;
34     int m, ans;
35     int a, b, k, x, order;
36     int arr[50010];
37     while(scanf("%d", &n) != EOF)
38     {
39         memset(c,0,sizeof(c));
40         for(i = 1; i <= n; ++i)
41             scanf("%d", &arr[i]);
42 
43         scanf("%d", &m);
44         while(m--) {
45             scanf("%d", &order);
46             if(order == 1) {
47                 scanf("%d %d %d %d", &a, &b, &k, &x);
48                // a--, b--;
49                 int kk = (b-a)/k;
50                 modify(k, a%k, a/k+1, x);
51                 modify(k, a%k, a/k+kk+2, -x);
52             }
53             else if(order == 2) {
54                 scanf("%d", &b);
55               //  b--;
56                 ans = arr[b];
57                 for(i = 1; i <= 10; ++i) {
58                     ans += getSum(i, b%i, b/i+1);
59                 }
60                 printf("%d\n", ans);
61             }
62         }
63     }
64 
65     return 0;
66 }

 

 

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4267

posted @ 2012-09-15 12:35  Griselda.  阅读(1493)  评论(0编辑  收藏  举报