http://acm.hdu.edu.cn/showproblem.php?pid=4267
题意就不多说了,由于需要更新的点都是离散的,按照普通线段树更新肯定是会超时的,但1 <= k <= 10,所以我们可以把k=1时,建立一颗线段树,k=2时建立对应模为0和1的两颗线段树,其他以此类推,共建立55颗线段树,这样更新时只要找到符合条件的线段树和区间就能和普通线段树一样更新了,而查询时需要找k=1,k=2,。。。k=10的相应的线段树,共查询10颗线段树,就能得到答案了。
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 #define lson l,m,rt<<1 5 #define rson m+1,r,rt<<1|1 6 #define maxn 50001 7 struct node{ 8 int setree[maxn<<2]; 9 }add[55]; 10 int num[maxn]; 11 void build(int i,int l,int r ,int rt) 12 { 13 add[i].setree[rt]=0; 14 if(l==r) 15 return; 16 int m=(l+r)>>1; 17 build(i,lson); 18 build(i,rson); 19 } 20 void pushdown(int i,int rt) 21 { 22 if(add[i].setree[rt]){ 23 add[i].setree[rt<<1]+=add[i].setree[rt]; 24 add[i].setree[rt<<1|1]+=add[i].setree[rt]; 25 add[i].setree[rt]=0; 26 } 27 } 28 void update(int i,int l,int r,int rt,int L,int R,int c) 29 { 30 if(L<=l&&r<=R){ 31 add[i].setree[rt]+=c; 32 return; 33 } 34 pushdown(i,rt); 35 int m=(l+r)>>1; 36 if(L<=m) 37 update(i,lson,L,R,c); 38 if(R>m) 39 update(i,rson,L,R,c); 40 } 41 int query(int i,int l,int r,int rt,int num) 42 { 43 if(l==r) 44 return add[i].setree[rt]; 45 int m=(l+r)>>1; 46 pushdown(i,rt); 47 if(num<=m) 48 return query(i,lson,num); 49 else 50 return query(i,rson,num); 51 } 52 int main() 53 { 54 int n; 55 while(~scanf("%d",&n)){ 56 for(int i=1;i<=n;i++) 57 scanf("%d",num+i); 58 for(int i=0;i<55;i++) 59 build(i,1,n,1); 60 int m; 61 scanf("%d",&m); 62 while(m--){ 63 int op; 64 scanf("%d",&op); 65 if(op==1){ 66 int a,b,k,c; 67 scanf("%d%d%d%d",&a,&b,&k,&c); 68 int num1=a/k; 69 if(a%k!=0) 70 num1++; 71 int num2=num1+(b-a+1)/k-1; 72 if((b-a+1)%k!=0) 73 num2++; 74 int rt=k*(k-1)/2+a%k; 75 update(rt,1,n,1,num1,num2,c); 76 } 77 else{ 78 int ans=0,a; 79 scanf("%d",&a); 80 for(int i=1;i<=10;i++){ 81 int num=a/i; 82 if(a%i!=0) 83 num++; 84 int rt=i*(i-1)/2+a%i; 85 ans+=query(rt,1,n,1,num); 86 } 87 printf("%d\n",num[a]+ans); 88 } 89 } 90 } 91 return 0; 92 }