http://acm.hust.edu.cn/vjudge/problem/31829/origin
题意:n个数
q次操作
每次操作 1: 区间更新【a,b,k,c】 对区间【a,b】从a开始每k个加c
2:单点查询【x】 查询x的值
如果用树状数组,直接暴力 每个k,以及对应的x%k 的余数 也是【0到k-1】开一个树状数组,也就是开【k】【k】个数组,
当时sb了没想到,用线段树做,开不了二维,只能开k个线段树
通过把下标重新映射,相当于把 第二维组织到一个线段树里了。。。下标太恶心了。。233
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const int N=51234;
int aa[N];
int sum[12][N*4];
int add[12][N*4];
int idx[12][12];
int num[12][12];
void pushDown(int i, int l, int r,int id) //把i节点的延迟标记传递到左右儿子节点
{
if(add[i] != 0)
{
int mid = (l + r) >> 1;
add[id][i << 1] += add[id][i];
sum[id][i << 1] += (mid - l + 1) * add[id][i]; //[l, mid]代表左儿子区间
add[id][i << 1 | 1] += add[id][i];
sum[id][i << 1 | 1] += (r - mid) * add[id][i]; //[mid + 1, r]代表右儿子区间
add[id][i] = 0;
}
}
void update(int i, int l, int r, int ql, int qr, int val,int id) //更新区间为qlqr,当前区间为l,r,代表当前区间和的节点为i,更新值为val,
{
if(l > qr || ql > r) //更新区间不在当前区间内
return ;
if(l >= ql && r <= qr) //要更新的区间把当前区间完全包括,则把当前整个区间+val,然后返回上一层
{
sum[id][i] += (r - l + 1) * val;
add[id][i] += val;
return ;
}
pushDown(i, l, r,id); //如果上面没reutrn 表示要往左右儿子区间查询,所以把延迟标记放下去
int mid = (l + r) >> 1;
update(i << 1, l, mid, ql, qr, val,id);
update(i << 1 | 1, mid + 1, r, ql, qr, val,id);
sum[id][i] = sum[id][i << 1] + sum[id][i << 1 | 1];
}
int query(int i, int l, int r, int ql, int qr,int id) //查询区间为qlqr,当前区间为l,r,代表当前区间和的节点为i
{
if(l > qr || ql > r)
return 0;
if(l >= ql && r <= qr)
return sum[id][i];
pushDown(i, l, r,id);
int mid =( l + r) >> 1;
return query(i << 1, l, mid, ql, qr,id)
+ query(i << 1 | 1, mid + 1, r, ql, qr,id);
}
void init()
{
memset(sum,0,sizeof sum);
memset(add,0,sizeof add);
memset(idx,0,sizeof idx);
memset(num,0,sizeof num);
}
int main()
{
//freopen("input.txt","r",stdin);
int n,q;
while(scanf("%d",&n)!=EOF)
{
init();
for (int i=1; i<=n; i++)
scanf("%d",&aa[i]);
for (int k=1; k<=10; k++)
{
num[k][0]=n/k;
for (int i=1; i<=k-1; i++)
{
num[k][i]=n/k+((n%k>=i)?1:0);
}
idx[k][0]=num[k][0]?1:0;
for (int i=1; i<=k-1; i++)
{
if (idx[k][i-1]==0)
idx[k][i]=1;
else
idx[k][i]=idx[k][i-1]+num[k][i-1];
}
}
/* for (int k=1; k<=10; k++)
{
for (int i=0; i<=k-1; i++)
{
printf("%d ",idx[k][i]);
}
printf("\n");
}*/
scanf("%d",&q);
int op;
int a,b,c,k;
for (int i=1; i<=q; i++)
{
scanf("%d",&op);
if (op==1)
{
scanf("%d%d%d%d",&a,&b,&k,&c);
int res=a%k;
int len=(b-a)/k;
int index=idx[k][res]+a/k;
if (a%k==0)index--;
//if (!len ) len++;
// printf("your inval : (%d,%d)\n",index,index+len-1);
update(1,1,n,index,index+len,c,k);
}
else
{
scanf("%d",&a);
int ans=0;
for (int j=1; j<=10; j++)
{
int index=idx[j][a%j]+a/j;
if (a%j==0)index--;
ans+= query(1,1,n,index,index,j);
}
printf("%d\n",ans+aa[a]);
}
}
}
}