题意:
n个数字
下面n个数字表示数列
2个操作
1 [u, v] k add
[u,v ]区间 (u点要计算)每隔k个位置,该数字+add
2 pos
询问 pos下标的值(下标从1开始)
思路:
因为k很小, 可以直接存 k[11]
注意查询时, 先找到 pos 所在的 叶子节点
再向上 添加 对应k位置的值
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string>
#include<queue>
#include<string.h>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<math.h>
#define inf 10000000
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define Mid(x,y) ((x+y)>>1)
#define ll __int64
using namespace std;
inline ll Min(ll a,ll b){return a>b?b:a;}
inline ll Max(ll a,ll b){return a<b?b:a;}
#define N 51000
struct node{
ll l, r;
ll k[11];
}tree[N*16];
ll a[N];
void build(ll l, ll r, ll id){
memset(tree[id].k, 0, sizeof(tree[id].k));
tree[id].l = l, tree[id].r = r;
if(l == r) return ;
ll mid = Mid(l, r);
build(l, mid, L(id));
build(mid+1, r, R(id));
}
void updata(ll l, ll r, ll pos, ll add, ll id){
if(l > r)return ;
if(l == tree[id].l && tree[id].r == r)
{
tree[id].k[pos] += add;
return;
}
ll mid = Mid(tree[id].l, tree[id].r);
if(r<=mid)
updata(l, r, pos, add, L(id));
else if(mid<l)
updata(l, r, pos, add, R(id));
else
{
updata(l, mid, pos, add, L(id));
updata(l + ((mid-l)/pos+1)*pos,r,pos, add, R(id));
}
}
ll find(ll pos){
ll id = 1;
while(1){
if(tree[id].l == tree[id].r) return id;
ll mid = Mid(tree[id].l, tree[id].r);
if(pos <= mid) id = L(id);
else id = R(id);
}
}
ll query(ll pos, ll id, ll num){
for(ll i =1;i<11 ;i++)
if((pos-tree[id].l) % i==0)
num += tree[id].k[i];
if(id == 1) return num;
return query(pos, id/2, num);
}
int main(){
ll i, j, n, que;
ll u, v, mod, add;
while(~scanf("%I64d",&n)){
for(i=1;i<=n;i++)scanf("%I64d",&a[i]);
build(1, n, 1);
scanf("%I64d",&que);
while(que--){
scanf("%I64d",&i);
if(i==2)
{
scanf("%I64d",&j);
printf("%I64d\n",query(j ,find(j), a[j]));
}
else
{
scanf("%I64d %I64d %I64d %I64d",&u,&v,&mod,&add);
updata(u, v, mod, add, 1);
}
}
}
return 0;
}
/*
10
0 0 0 0 0 0 0 0 0 0
99
1 1 10 2 5
2 1
2 2
2 3
2 4
2 5
2 9
2 10
1 3 6 3 10
2 3
2 4
2 5
2 6
ans:
5
0
5
0
5
5
0
15
0
5
10
*/