一个长度为n的数组 每次对lr区间进行修改 如果要修改i 则对i i*2 i*3...都修改 最后单点查询值
思想是利用树状数组维护每一个区间的更新值 查询的时候得出这个点的所有因子的查询值的和 加上这个点的最初值
因为对树状数组理解不深再次错过绝杀...
由于是维护每个点的修改量 所以每次修改 都进行add(l,val) add(r+1,-val)
这时候 如果要求单点的修改值 需要sum(x) 而非sum(x)-sum(x-1)
因为没有将初值进行add 所以c数组存放的其实不是一个前缀和 而是一个差分 差分的前缀和就是差分值
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define L long long
#define pb push_back
L n ;
L a[300050] ;
vector<L >v[1000050] ;
L c[3000050] ;
L lowbit(L x){
return (x&-x);
}
void add(L x,L w)
{
while(x<=n)
{
c[x]+=w;
x+=lowbit(x);
}
}
L sum(L x)
{
L tot=0;
while(x)
{
tot+=c[x];
x-=lowbit(x);
}
return tot;
}
int main(){
scanf("%lld",&n);
for(L i = 1; i <= n ; i ++ )
scanf("%lld",&a[i]);
for(L i = 1; i <= n ; i ++ ){
for(L j = 1; j * i <= n ; j ++) {
v[j*i].pb(i) ;
}
}
memset(c,0,sizeof(c));
L q;
scanf("%lld",&q);
while(q--){
L op;
scanf("%lld",&op);
if(op==2){
L l , r;
L val;
scanf("%lld%lld%lld",&l,&r,&val);
add(l,val);
add(r+1,-val);
}
else {
L w;
scanf("%lld",&w);
L ans=0;
for(L i=0;i<v[w].size();i++){
L x=v[w][i];
ans += sum(x) ;
}
printf("%lld\n",ans+a[w]);
}
}
}
..我的绝杀..