当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); } } }