这道题拿过来感觉很蒙 , 因为以前做的都是点更新询问区间 , 或是区间更新询问点 , 这道题是在[a,b]区间内隔k个数更新一次( (i - a) % k == 0即i%k==a%k), 对于树状数组来说按照一维的方式定义, 后面在加上两维 c[i][k][i%k] (a<=i<=b), 相当于在一维c[i]每个节点加入了一些信息,来记录每次更新,询问时候再加上原数组即可得到结果。
#include <iostream> #include <stdio.h> #include <string> #include <string.h> #include <algorithm> using namespace std ; const int maxn = 50005; int num[maxn]; int c[maxn][11][11]; int lowbit(int x){ return x&(-x); } void update(int v,int k,int ik,int val){ for(int i = v;i > 0;i-=lowbit(i)) c[i][k][ik] += val; } int query(int v){ int ans = 0; for(int i = v;i < maxn;i+=lowbit(i)){ for(int j = 1;j <= 10;j++) ans += c[i][j][v%j]; } return ans; } int main(){ int n; while(~scanf("%d",&n)){ memset(c,0,sizeof(c)); for(int i = 1;i <= n;i++) scanf("%d",num+i); int q; scanf("%d",&q); while(q--){ int f,a,b,k,c; scanf("%d",&f); if(f == 1){ scanf("%d%d%d%d",&a,&b,&k,&c); update(a-1,k,a%k,-c); update(b,k,a%k,c); } else{ scanf("%d",&a); printf("%d\n",query(a)+num[a]); } } } return 0 ; }