zkw线段树模板练习。

orz今天写了三遍

另外我只写了区间修改和求和。为啥呢?因为我菜啊qwq

#include<iostream>
#include<cstdio>
#define maxn 200001
#define int long long
using namespace std;
int n, m;
int sum[maxn*2], add[maxn*2]; 
void build(){
	for(m=1; m<=n; m<<=1);
	for(int i=m+1; i<=m+n; i++)
		scanf("%lld", &sum[i]);
	for(int i=m-1; i; i--)
		sum[i]=sum[i<<1]+sum[i<<1|1];
}
inline int query_part(int s, int t){
	int lc=0, rc=0, len=1, ans=0;
	for(s+=m-1, t+=m+1; s^t^1; s>>=1, t>>=1, len<<=1){
		if(s&1^1) ans+=sum[s^1]+len*add[s^1], lc+=len;
		if(t&1) ans+=sum[t^1]+len*add[t^1], rc+=len;
		if(add[s>>1]) ans+=add[s>>1]*lc;
		if(add[t>>1]) ans+=add[t>>1]*rc;
	}
	s>>=1; 
	for(lc+=rc; s; s>>=1)
		if(add[s]) ans+=add[s]*lc;
	return ans;
}
inline int update(int s, int t, int v){
	int lc=0, rc=0, len=1;
	for(s+=m-1, t+=m+1; s^t^1; s>>=1, t>>=1, len<<=1){
		if(s&1^1) add[s^1]+=v, lc+=len;
		if(t&1)   add[t^1]+=v, rc+=len;
		sum[s>>1]+=v*lc, sum[t>>1]+=v*rc;
	}
	for(lc+=rc; s; s>>=1)
		sum[s>>1]+=v*lc;
}
int q;
signed main(){
	scanf("%lld%lld", &n, &q);
	build();
	int qwq, x, y, k;
	while(q--){
		scanf("%lld", &qwq);
		if(qwq==1){
			scanf("%lld%lld%lld", &x, &y, &k);
			update(x, y, k);
		}else{
			scanf("%lld%lld", &x, &y);
			printf("%lld\n", query_part(x, y));
		}
	}
	return 0;
}
posted @ 2018-11-09 09:03  PushinL  阅读(262)  评论(0编辑  收藏  举报