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 }