当d<=sqrt(n)时 直接暴力修改树状数组的值会使复杂度退化到O(n²)
所以这里要用到分块的思想,修改lazy标记
lazy[i]表示i的倍数的位置中所有的数组成的一个块,查询时l到r对应的lazy,这中间有r/i-(l-1)/i个数,乘以lazy[i]就是分块记录的答案
跟树状数组直接记录的答案相加就是最终的答案
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,m;
const int N=100010;
int c[N];
int lazy[1000];
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int k)
{
while(x<=n)
{
c[x]+=k;
x+=lowbit(x);
}
}
int getsum(int x)
{
int ans=0;
while(x>=1)
{
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
signed main()
{
scanf("%lld%lld",&n,&m);
while(m--)
{
int op;
scanf("%lld",&op);
if(op==1)
{
int d,k;
scanf("%lld%lld",&d,&k);
if(d<=sqrt(n))
{
lazy[d]+=k;
}
else
{
for(int i=d;i<=n;i+=d)
{
update(i,k);
}
}
}
else
{
int l,r;
scanf("%lld%lld",&l,&r);
int ans=getsum(r)-getsum(l-1);
for(int i=1;i<=sqrt(n);i++)
ans+=((r/i)-(l-1)/i)*lazy[i];
printf("%lld\n",ans);
}
}
}


京公网安备 11010502036488号