牛客 19246 数据结构 线段树维护区间平方和

回顾一下线段树求幂次方和的操作

#include
using namespace std;
const int N = 1e4+100;
typedef long long ll;
struct segtree{
	#define lson id<<1,l,mid
	#define rson id<<1|1,mid+1,r
	ll sum[N<<2],add[N<<2],mul[N<<2],sum2[N<<2];
	void cal(int id,ll c,ll d,ll len){
		sum2[id]=(sum2[id]*d*d+2ll*sum[id]*c*d+c*c*len);
		sum[id]=sum[id]*d+c*len;
		mul[id]*=d;
		add[id]=add[id]*d+c;
	}
	void pushdown(int id,int l,int r){
		int mid = l+r>>1;
		if(add[id]||mul[id]!=1){
			cal(id<<1,add[id],mul[id],mid-l+1);
			cal(id<<1|1,add[id],mul[id],r-mid);
			add[id]=0,mul[id]=1;
		}
	}
	void pushup(int id){
		sum[id]=sum[id<<1]+sum[id<<1|1];
		sum2[id]=sum2[id<<1]+sum2[id<<1|1];
	}
	void build(int id,int l,int r){
		mul[id]=1;add[id]=0;
		if(l==r){
			scanf("%lld",&sum[id]);
			sum2[id]=sum[id]*sum[id];
			return;
		}
		int mid = l+r>>1;
		build(lson);build(rson);
		pushup(id);
	}	
	ll query(int id,int l,int r,int L,int R,int op){
		if(L<=l&&R>=r){
			return op?sum[id]:sum2[id];
		}
		pushdown(id,l,r);
		int mid = l+r>>1;
		ll ans = 0;
		if(L<=mid) ans+=query(lson,L,R,op);
		if(R>mid) ans+=query(rson,L,R,op);
		return ans;
	}	
	void update(int id,int l,int r,int L,int R,ll c,ll d){
		if(L<=l&&R>=r){
			cal(id,c,d,r-l+1);
			return;
		}
		int mid = l+r>>1;
		pushdown(id,l,r);
		if(L<=mid) update(lson,L,R,c,d);
		if(R>mid) update(rson,L,R,c,d);
		pushup(id);
	}
}s;
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	s.build(1,1,n);
	for(int i = 1; i <= m; i++){
		int op,l,r;ll x;
		scanf("%d%d%d",&op,&l,&r);
		if(op<=2){
			printf("%lld\n",s.query(1,1,n,l,r,op%2));
		}else{
			scanf("%lld",&x);
			if(op==3) s.update(1,1,n,l,r,0,x);
			else s.update(1,1,n,l,r,x,1);
		}
	}
	return 0;
}

 

你可能感兴趣的:(线段树)