HDU 4267 A Simple Problem with Integers
题目大意:对一个长度为n(n <= 50000)的数列A进行m(m <= 50000)次操作(2种):
1:给定a,b,k,c四个整数,在[a , b] 区间满足a<=i<=b && (i-a)% k == 0的数加c(1<=k<=10);
2:给定整数a,求当前A[a];
题解:首先,这是线段修改,单点查询的问题,可以用树状数组解决,但是由于数据不是连续的所以,采用划分成多个树状数组的方式来完成。我们按照数列的首项和公差将其划分为55个树状数组,然后进行统计。
#include <cstdio> #include <iostream> using namespace std; const int MAXN=50005; int c[105][MAXN],begin[MAXN],n,m; void update(int k,int x,int val){while(x<=n)c[k][x]+=val,x+=x&-x;} int getsum(int pos){ int s=0; for(int i=1;i<=10;i++){ int k=10*(i-1)+pos%i,x=pos; while(x)s+=c[k][x],x-=x&-x; }return s+begin[pos]; } int main(){ int a,b,k,num,q; while(~scanf("%d",&n)){ memset(c,0,sizeof(c)); for(int i=1;i<=n;i++)scanf("%d",&begin[i]); scanf("%d",&m); while(m--){ scanf("%d",&q); if(q==1){ scanf("%d%d%d%d",&a,&b,&k,&num); b-=(b-a)%k; update(10*(k-1)+a%k,a,num); update(10*(k-1)+a%k,b+1,-num); }else scanf("%d",&a),printf("%d\n",getsum(a)); } } return 0; }
愿你出走半生,归来仍是少年