ac code:
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+1;
typedef long long ll;
int n,f,tot=0,m,l[N],r[N],cur[N];
ll fs[N],sum[N]={0},res[N]={0};
void change(int L,int R,ll k){
for(int i=L;i<=min(tot*cur[L],R);i++)
fs[i]+=k,sum[cur[i]]+=k;
if(cur[L]==cur[R]) return;
for(int i=(cur[R]-1)*tot+1;i<=R;i++)
fs[i]+=k,sum[cur[i]]+=k;
for(int i=cur[L]+1;i<cur[R];i++)
res[i]+=k;
}
ll get_sum(int L,int R){
ll ans=0;
for(int i=L;i<=min(cur[L]*tot,R);i++)
ans+=(fs[i]+res[cur[i]]);
if(cur[L]==cur[R]) return ans;
for(int i=(cur[R]-1)*tot+1;i<=R;i++)
ans+=fs[i]+res[cur[i]];
for(int i=cur[L]+1;i<cur[R];i++)
ans+=sum[i]+tot*res[i];
return ans;
}
int main(){
scanf("%d%d",&n,&f);
tot=m=sqrt(n);
m= m*m==n ? m : m+1;
for(int i=1;i<=n;i++) {
scanf("%lld",&fs[i]);
cur[i]=(i-1)/tot+1;
sum[cur[i]]+=fs[i];
}
while(f--){
int op,L,R; ll k; scanf("%d",&op);
if(op==1){
scanf("%d%d%lld",&L,&R,&k);
change(L,R,k);
} else if(op==2){
scanf("%lld",&k);
change(1,1,k);
} else if(op==3){
scanf("%lld",&k);
change(1,1,-k);
} else if(op==4){
scanf("%d%d",&L,&R);
printf("%lld\n",get_sum(L,R));
} else printf("%lld\n",fs[1]+res[1]);
}
}
块区间首位标记是通过cur[](原序列元素所在块编号)计算出来
wa code :
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+1;
typedef long long ll;
int n,f,tot=0,m,l[N],r[N],cur[N];
ll fs[N],sum[N]={0},res[N]={0};
void change(int L,int R,ll k){
for(int i=L;i<=min(r[cur[L]],R);i++)
fs[i]+=k,sum[cur[i]]+=k;
if(cur[L]==cur[R]) return;
for(int i=l[cur[R]];i<=R;i++)
fs[i]+=k,sum[cur[i]]+=k;
for(int i=cur[L]+1;i<cur[R];i++)
res[i]+=k;
}
ll get_sum(int L,int R){
ll ans=0;
for(int i=L;i<=min(r[cur[L]],R);i++)
ans+=(fs[i]+res[cur[i]]);
if(cur[L]==cur[R]) return ans;
for(int i=l[cur[R]];i<=R;i++)
ans+=fs[i]+res[cur[i]];
for(int i=cur[L]+1;i<cur[R];i++)
ans+=sum[i]+tot*res[i];
return ans;
}
int main(){
scanf("%d%d",&n,&f);
tot=m=sqrt(n);
m= m*m==n ? m : m+1;
for(int i=1;i<=n;i++) {
scanf("%lld",&fs[i]);
cur[i]=(i-1)/tot+1;
}
for(int i=1;i<=m;i++){
l[i]=(i-1)*tot+1,r[i]= i*tot<=n ? i*tot : n;
for(int j=l[i];j<=r[i];j++) sum[i]+=fs[j];
}
while(f--){
int op,L,R; ll k; scanf("%d",&op);
if(op==1){
scanf("%d%d%lld",&L,&R,&k);
change(L,R,k);
} else if(op==2){
scanf("%lld",&k);
change(1,1,k);
} else if(op==3){
scanf("%lld",&k);
change(1,1,-k);
} else if(op==4){
scanf("%d%d",&L,&R);
printf("%lld\n",get_sum(L,R));
} else printf("%lld\n",fs[1]+res[1]);
}
}
在在线之前预处理出来各个元素所在的块(cur[])与块的区间(l[],r[])
一份AC一份只有45分 ,求教为什么