题意:
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 */