hdu 4267 多维树状数组

题意:有一个序列

"1 a b k c" means adding c to each of Ai which satisfies a <= i <= b and (i - a) % k == 0. (1 <= a <= b <= N, 1 <= k <= 10, -1,000 <= c <= 1,000)
"2 a" means querying the value of Aa. (1 <= a <= N)

分析转自:http://www.cnblogs.com/Griselda/archive/2012/09/15/2686133.html

感觉是树状数组了

但是 树状数组是单点更新 而题目要求是在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个树状数组.

 

建出来的树并不是普通的1,2,3,4,这样的,而是有着间隔的,其实也就是建造了许多树状数组

 

 1 #include<stdio.h>

 2 

 3 #include<queue>

 4 #include<iostream>

 5 #include<algorithm>

 6 #include<string.h>

 7 const int MAXN=50020;

 8 

 9 

10 int c[12][12][MAXN];

11 int n;

12 

13 int lowbit(int x)

14 {

15     return x&(-x);

16 }

17 

18 void update(int t1,int t2,int i,int val)

19 {

20     while(i<=n)

21     {

22         c[t1][t2][i]+=val;

23         i+=lowbit(i);

24     }

25 

26 }

27 int sum(int t1,int t2,int i)

28 {

29 

30     int s=0;

31     while(i>0)

32     {

33         s+=c[t1][t2][i];

34         i-=lowbit(i);

35     }

36     return s;

37 }

38 int num[MAXN];

39 int main()

40 {

41     #ifndef ONLINE_JUDGE

42     freopen("1.in","r",stdin);

43     #endif

44     int m;

45     while(scanf("%d",&n)!=EOF)

46     {

47         for(int i=0;i<n;i++)scanf("%d",&num[i]);

48         for(int i=0;i<12;i++)

49           for(int j=0;j<12;j++)

50             for(int k=0;k<MAXN;k++)

51               c[i][j][k]=0;

52         scanf("%d",&m);

53         int a,b,k,q;

54         int t;

55         while(m--)

56         {

57             scanf("%d",&t);

58             if(t==1)

59             {

60                 scanf("%d%d%d%d",&a,&b,&k,&q);

61                 a--;

62                 b--;

63                 int num=(b-a)/k;    

64                 int s=a%k-1;

65                 update(k,s,a/k+1,q);    //s是该数组的开头数字,a/k+1是结尾的数字

66                 update(k,s,a/k+num+2,-q);

67             }

68             else

69             {

70                 scanf("%d",&a);

71                 a--;

72                 int ss=num[a];

73                 for(int i=1;i<=10;i++)

74                 {

75                     ss+=sum(i,a%i-1,a/i+1);

76                 }

77                 printf("%d\n",ss);

78             }

79         }

80     }

81     return 0;

82 }

 

你可能感兴趣的:(树状数组)