题意
给出一个长为 n 的数列,以及 n 个操作,操作涉及区间加法,区间求和。
题解
维护两个标记,一个是区间和,一个是tag表示该区间总共打了多少加法。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int nmax = 5e4 + 100;
const int INF = 0x3f3f3f3f;
const int mm = sqrt(5e4 + 100) + 10;
int n,m;
ll data[nmax],tag[mm],sum[mm];
int L[mm],R[mm],belong[nmax],block,num;
void init(){
block = sqrt(n);
num = n / block; if(num % block) num++;
for(int i = 1;i<=num;++i){
L[i] = (i-1) * block + 1;
R[i] = i * block;
}
R[num] = n;
}
int main() {
scanf("%d",&n);
init();
for(int i = 1;i<=n;++i){
scanf("%lld",&data[i]);
belong[i] = (i-1) / block + 1;
sum[belong[i]] += data[i];
}
int op,l,r; ll w;
for(int i = 1;i<=n;++i){
scanf("%d %d %d %lld",&op,&l,&r,&w);
if(op == 0){
for(int j = l;j<=min(R[belong[l]],r);++j) data[j] += w, sum[belong[j]] += w;
if(belong[l] != belong[r]) for(int j = L[belong[r]];j<=r;++j) data[j] += w,sum[belong[j]] += w;
for(int j = belong[l] + 1;j<=belong[r]-1;++j) sum[j] += w * block, tag[j] += w;
}else{
ll ans = 0;
for(int j = l;j<=min(R[belong[l]],r);++j) ans = (ans + data[j] + tag[belong[j]]);
if(belong[l] != belong[r]) for(int j = L[belong[r]];j<=r;++j) ans = (ans + data[j] + tag[belong[j]]);
for(int j = belong[l] + 1;j<=belong[r] -1;++j) ans = (ans + sum[j]) ;
printf("%lld\n",ans% (w+1));
}
}
return 0;
}