https://www.nowcoder.com/acm/contest/200/B
op = 1 sum
op = 2 sum2 平方和
op = 3 *mul
op = 4 +add
2个lazy标记
#include <cstdio>
#include <iostream>
using namespace std;
#define lc (rt << 1)
#define rc (rt << 1 | 1)
#define mid (l + r) / 2
typedef long long ll;
const int maxn = 1e4 + 5;
ll a[maxn];
ll sum[maxn << 2],sum2[maxn << 2];
ll _sum,_sum2;
ll mul[maxn << 2];
ll add[maxn << 2];
void init(int l,int r,int rt)
{
if(l == r){
sum[rt] = a[l];
sum2[rt] = a[l] * a[l];
mul[rt] = 1;
add[rt] = 0;
return;
}
init(l,mid,lc);
init(mid + 1,r,rc);
sum[rt] = sum[lc] + sum[rc];
sum2[rt] = sum2[lc] + sum2[rc];
mul[rt] = 1;
add[rt] = 0;
}
//一定要先更新sum2,因为它用到了旧的sum
//如果2个标记分开处理,先确定顺序,第一个标记除了update中操作,还更新d第二个标记;第二个标记就是update操作
void pushdown(int l,int r,int rt)
{
if(mul[rt] != 1){
mul[lc] *= mul[rt];mul[rc] *= mul[rt];
add[lc] *= mul[rt];
add[rc] *= mul[rt];
sum2[lc] *= mul[rt] * mul[rt];sum2[rc] *= mul[rt] * mul[rt];
sum[lc] *= mul[rt];sum[rc] *= mul[rt];
mul[rt] = 1;
}
if(add[rt] != 0){
add[lc] += add[rt];add[rc] += add[rt];
sum2[lc] += 2 * sum[lc] * add[rt] + (mid - l + 1) * add[rt] * add[rt];
sum2[rc] += 2 * sum[rc] * add[rt] + (r - mid) * add[rt] * add[rt];
sum[lc] += add[rt] * (mid - l + 1);sum[rc] += add[rt] * (r - mid);
add[rt] = 0;
}
}
//左子树原x1*a+y1 将父节点传递->x*(x1*a+y1)+y
//void pushdown(int l,int r,int rt)
//{
// if(mul[rt] == 1 && add[rt] == 0) return;
// mul[lc] *= mul[rt];mul[rc] *= mul[rt];
// add[lc] = add[lc] * mul[rt] + add[rt];
// add[rc] = add[rc] * mul[rt] + add[rt];
// sum2[lc] = mul[rt] * mul[rt] * sum2[lc] + 2 * mul[rt] * add[rt] * sum[lc] + (mid - l + 1) * add[rt] * add[rt];
// sum2[rc] = mul[rt] * mul[rt] * sum2[rc] + 2 * mul[rt] * add[rt] * sum[rc] + (r - mid) * add[rt] * add[rt];
//
// sum[lc] = sum[lc] * mul[rt] + add[rt] * (mid - l + 1);
// sum[rc] = sum[rc] * mul[rt] + add[rt] * (r - mid);
// mul[rt] = 1;add[rt] = 0;
//}
void query(int ql,int qr,int l,int r,int rt)
{
if(ql <= l && r <= qr){
_sum += sum[rt];
_sum2 += sum2[rt];
return;
}
pushdown(l,r,rt);
if(ql <= mid) query(ql,qr,l,mid,lc);
if(mid < qr) query(ql,qr,mid + 1,r,rc);
}
void update1(int ql,int qr,int l,int r,int rt,ll x)
{
if(ql <= l && r <= qr){
sum2[rt] *= x * x;
sum[rt] *= x;
mul[rt] *= x;
return;
}
pushdown(l,r,rt);
if(ql <= mid) update1(ql,qr,l,mid,lc,x );
if(mid < qr) update1(ql,qr,mid + 1,r,rc,x );
sum[rt] = sum[lc] + sum[rc];
sum2[rt] = sum2[lc] + sum2[rc];
}
void update2(int ql,int qr,int l,int r,int rt,ll x)
{
if(ql <= l && r <= qr){
sum2[rt] += 2 * x * sum[rt] + (r - l + 1) * x * x;
sum[rt] += x * (r - l + 1);
add[rt] += x;
return;
}
pushdown(l,r,rt);
if(ql <= mid) update2(ql,qr,l,mid,lc,x );
if(mid < qr) update2(ql,qr,mid + 1,r,rc,x );
sum[rt] = sum[lc] + sum[rc];
sum2[rt] = sum2[lc] + sum2[rc];
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i ++) scanf("%lld",&a[i]);
init(1,n,1);
int op,ql,qr;
ll x;
for(int i =0 ;i < m;i ++){
scanf("%d",&op);
_sum = _sum2 = 0;
if(op == 1){
scanf("%d%d",&ql,&qr);
query(ql,qr,1,n,1);
printf("%lld\n",_sum);
}
else if(op == 2){
scanf("%d%d",&ql,&qr);
query(ql,qr,1,n,1);
printf("%lld\n",_sum2);
}
else if(op == 3){
scanf("%d%d%lld",&ql,&qr,&x);
update1(ql, qr, 1, n, 1, x);
}
else if(op == 4){
scanf("%d%d%lld",&ql,&qr,&x);
update2(ql,qr,1,n,1,x);
}
}
return 0;
}