按余数对数分组,tree[i][j]表示被i除余j的数的序列; 然后用10*10个树状数组就可以做了。是区间更新,单点求值。
#include<stdio.h>
#define lowbit(x) ((x)&(-x))
#include<string.h>
int tree[11][11][50002];
int a[50002]; int n;
void update(int k,int i,int j,int c)
{
while(j<=n+10)
{
tree[k][i][j]+=c;
j+=lowbit(j);
}
}
int getsum(int k,int i,int x)
{
int sum=0;
while(x>0)
{
sum+=tree[k][i][x];
x-=lowbit(x);
}
return sum;
}
int main()
{
int i,j,q; int sign,k; int l,r,c,pos;
while(~scanf("%d",&n))
{
memset(tree,0,sizeof(tree));
for(i=1;i<=n;i++) scanf("%d",a+i);
scanf("%d",&q);
for(i=1;i<=q;i++)
{
scanf("%d",&sign);
if( sign==1 )
{
scanf("%d%d%d%d",&l,&r,&k,&c);
j=l%k;
l=(l/k)+1;
if( r%k >= j) r=(r/k) +1 ; else r=r/k;
update(k,j,l,c);
update(k,j,r+1,-c);
}
else
{
scanf("%d",&pos);
int ans; ans=0;
for(k=1;k<=10;k++)
ans+=getsum(k,pos%k,(pos/k)+1);
printf("%d\n",ans+a[pos]);
}
}
}
return 0;
}