思路
要维护区间和以及平方和两个线段树,同时支持加法和乘法操作。
前面基本套模板就行了,那么我们重点是pushdown怎么写。
(这个板子是参照oi-wiki先打出lazy的pushdown的,已经能支持加法维护区间和了)
我们可以用上述式子Pushdown区间平方和。
考虑乘法:
一开始我们建立cheng记录结点需要pushdown的乘数,在往下传递的过程中
这样两个线段树的更新操作就完成了。
代码
#include<bits/stdc++.h>
#define int ll
typedef long long ll;
using namespace std;
const int maxn=10005;
int n,m,opt,l,r,x;
int num[maxn],tree[maxn*4],fang[maxn*4];
int lazy[maxn*4],cheng[maxn*4];
inline void read(int &data){
int x=0,flag=1;char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') flag=flag*-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
data=x*flag;
}
void pushdown(int node,int start,int end){
int mid=start+end>>1;
lazy[node<<1]*=cheng[node];
lazy[node<<1|1]*=cheng[node];
cheng[node<<1]*=cheng[node];
cheng[node<<1|1]*=cheng[node];
tree[node<<1]*=cheng[node];
tree[node<<1|1]*=cheng[node];
fang[node<<1]*=cheng[node]*cheng[node];
fang[node<<1|1]*=cheng[node]*cheng[node];
cheng[node]=1;
if(lazy[node]){
lazy[node<<1]+=lazy[node];
lazy[node<<1|1]+=lazy[node];
fang[node<<1]+=2*lazy[node]*tree[node<<1]+(mid-start+1)*lazy[node]*lazy[node];
fang[node<<1|1]+=2*lazy[node]*tree[node<<1|1]+(end-mid)*lazy[node]*lazy[node];
tree[node<<1]+=lazy[node]*(mid-start+1);
tree[node<<1|1]+=lazy[node]*(end-mid);
lazy[node]=0;
}
}
void pushup(int node){
tree[node]=tree[node<<1]+tree[node<<1|1];
fang[node]=fang[node<<1]+fang[node<<1|1];
}
void build(int node,int start,int end){
lazy[node]=0;cheng[node]=1;
if(start==end){
tree[node]=num[start];
fang[node]=tree[node]*tree[node];
return;
}
int mid=start+end>>1;
build(node<<1,start,mid);
build(node<<1|1,mid+1,end);
pushup(node);
}
int query1(int node,int start,int end,int l,int r){
if(l<=start&&end<=r) return tree[node];
int mid=start+end>>1;
pushdown(node,start,end);
int res=0;
if(l<=mid) res+=query1(node<<1,start,mid,l,r);
if(r>mid) res+=query1(node<<1|1,mid+1,end,l,r);
return res;
}
int query2(int node,int start,int end,int l,int r){
if(l<=start&&end<=r) return fang[node];
int mid=start+end>>1;
pushdown(node,start,end);
int res=0;
if(l<=mid) res+=query2(node<<1,start,mid,l,r);
if(r>mid) res+=query2(node<<1|1,mid+1,end,l,r);
return res;
}
void add(int node,int start,int end,int l,int r,int val){
if(l<=start&&end<=r){
lazy[node]+=val;
fang[node]+=2*val*tree[node]+(end-start+1)*val*val;
tree[node]+=(end-start+1)*val;
return;
}
int mid=start+end>>1;
pushdown(node,start,end);
if(l<=mid) add(node<<1,start,mid,l,r,val);
if(r>mid) add(node<<1|1,mid+1,end,l,r,val);
pushup(node);
}
void multi(int node,int start,int end,int l,int r,int val){
if(l<=start&&end<=r){
lazy[node]*=val;
cheng[node]*=val;
tree[node]*=val;
fang[node]*=val*val;
return;
}
int mid=start+end>>1;
pushdown(node,start,end);
if(l<=mid) multi(node<<1,start,mid,l,r,val);
if(r>mid) multi(node<<1|1,mid+1,end,l,r,val);
pushup(node);
}
signed main(){
read(n);read(m);
for(int i=1;i<=n;i++) read(num[i]);
build(1,1,n);
for(int i=1;i<=m;i++){
read(opt);
if(opt==1){
read(l);read(r);
printf("%lld\n",query1(1,1,n,l,r));
}
if(opt==2){
read(l);read(r);
printf("%lld\n",query2(1,1,n,l,r));
}
if(opt==3){
read(l);read(r);read(x);
multi(1,1,n,l,r,x);
}
if(opt==4){
read(l);read(r);read(x);
add(1,1,n,l,r,x);
}
}
return 0;
} 
京公网安备 11010502036488号