给出一个长度为 n n n 的序列 a a a,有 m m m 次操作,格式如下:
1 x y k
对于所有满足 ( i − 1 ) m o d x ≤ y (i-1) \bmod x \le y (i−1)modx≤y 的 i i i,将 a i a_i ai 的值加 k k k。
2 l r
求 ∑ i = l r a i \sum\limits_{i=l}^r a_i i=l∑rai 。
数组下标从 1 1 1 开始。
n , m ≤ 2 × 1 0 5 , a i , k ≤ 1 0 9 , 1 ≤ x , y ≤ n n,m\le2\times 10^5,a_i,k\le10^9,1\le x,y\le n n,m≤2×105,ai,k≤109,1≤x,y≤n
又是ex数据结构题。考虑根号分治,分成 x ≤ n x\le \sqrt n x≤n 和 x > n x>\sqrt n x>n 两部分处理。
时间复杂度 O ( n n ) O(n\sqrt n) O(nn)。本题卡常,下面代码看看就好。
#include
#define rg register
using namespace std;
#define ll long long
const int N=2e5+1,NN=1000;
int n,m,block,ID[N];
ll g[NN][NN],sum[N];
ll bj1[N],bj2[N],Bj1[N],Bj2[N];
inline void update(int x,int k)
{
if(x>n) return;
bj1[x]+=k;
Bj1[ID[x]]+=k;
bj2[x]+=1ll*x*k;
Bj2[ID[x]]+=1ll*x*k;
}
inline ll query1(int l,int r)
{
ll ans=0;
int lid=ID[l],rid=ID[r];
if(lid==rid){
for(rg int i=l;i<=r;i++) ans+=bj1[i];
return ans;
}
for(rg int i=lid*block+block;i>=l;i--) ans+=bj1[i];
for(rg int i=lid+1;i<rid;i++) ans+=Bj1[i];
for(rg int i=rid*block+1;i<=r;i++) ans+=bj1[i];
return ans;
}
inline ll query2(int l,int r)
{
ll ans=0;
int lid=ID[l],rid=ID[r];
if(lid==rid){
for(rg int i=l;i<=r;i++) ans+=bj2[i];
return ans;
}
for(rg int i=lid*block+block;i>=l;i--) ans+=bj2[i];
for(rg int i=lid+1;i<rid;i++) ans+=Bj2[i];
for(rg int i=rid*block+1;i<=r;i++) ans+=bj2[i];
return ans;
}
int main()
{
freopen("scarlet.in","r",stdin);
freopen("scarlet.out","w",stdout);
cin.tie(0)->sync_with_stdio(0);
cin>>n>>m;
block=sqrt(n);
if(n>=100) block=block*0.55;
for(rg int i=1,x;i<=n;i++) cin>>x,sum[i]=sum[i-1]+x,ID[i]=(i-1)/block;
for(rg int t=1,op,x,y,k,l,r;t<=m;t++){
cin>>op;
if(op==1){
cin>>x>>y>>k;
y=min(x-1,y);
if(x<=block){
ll K=k;
for(rg int i=0;i<=y;i++,K+=k) g[x][i]+=K;
K-=k;
for(rg int i=y+1;i<x;i++) g[x][i]+=K;
}
else{
for(rg int i=1;i<=n;i+=x){
update(i,k);
update(i+y+1,-k);
}
}
}
else{
cin>>l>>r;
ll ans=sum[r]-sum[l-1];
for(rg int i=1;i<=block;i++){
int lid=(l-1)/i,rid=(r-1)/i,L=(l-1)-lid*i,R=(r-1)-rid*i;
ans+=(rid-lid)*g[i][i-1]+g[i][R]-(L?g[i][L-1]:0);
}
cout<<ans+(r-l+1)*query1(1,l-1)+query1(l,r)*(r+1)-query2(l,r)<<"\n";
}
}
}