http://acm.hdu.edu.cn/showproblem.php?pid=4267
【思路】
- 树状数组的区间修改:在区间[a, b]内更新+x就在a的位置+x. 然后在b+1的位置-x
-
树状数组的单点查询:求某点a的值就是求数组中1~a的和.
- (i-a)%k==0把区间分隔开了,不能直接套用树状数组的区间修改单点查询
- 这道题的K很小,所以可以枚举k,对于每个k,建立k个树状数组,所以一共建立55棵树
-
所以就可以多建几棵树..然后就可以转换为成段更新了~~
【AC】
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int n; 5 const int maxn=5e4+2; 6 int tree[12][12][maxn]; 7 int a[maxn]; 8 int lowbit(int x) 9 { 10 return x&(-x); 11 } 12 void add(int k,int x,int pos,int val) 13 { 14 while(pos<=n) 15 { 16 tree[k][x][pos]+=val; 17 pos+=lowbit(pos); 18 } 19 } 20 21 int query(int k,int x,int pos) 22 { 23 int res=0; 24 while(pos) 25 { 26 res+=tree[k][x][pos]; 27 pos-=lowbit(pos); 28 } 29 return res; 30 } 31 int main() 32 { 33 while(~scanf("%d",&n)) 34 { 35 memset(tree,0,sizeof(tree)); 36 for(int i=1;i<=n;i++) 37 { 38 scanf("%d",&a[i]); 39 } 40 int q; 41 scanf("%d",&q); 42 while(q--) 43 { 44 int tp; 45 scanf("%d",&tp); 46 if(tp==1) 47 { 48 int x,y,k,c; 49 scanf("%d%d%d%d",&x,&y,&k,&c); 50 int st=x/k; 51 if(x%k) st++; 52 int ed=st+(y-x)/k; 53 add(k,x%k,st,c); 54 add(k,x%k,ed+1,-c); 55 } 56 else 57 { 58 int x; 59 scanf("%d",&x); 60 int ans=a[x]; 61 int pos; 62 for(int i=1;i<=10;i++) 63 { 64 pos=x/i; 65 if(x%i) pos++; 66 ans+=query(i,x%i,pos); 67 } 68 printf("%d ",ans); 69 } 70 } 71 } 72 return 0; 73 }