线段树(区间修改,区间查询)

正常的线段树板子awa

#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdio>

#define lid ( id << 1 )
#define rid ( id << 1 | 1 )

using namespace std;

long long num[114514],n,m;
long long a,b,c;
string ope;

struct sigment_tree {
	long long l;
	long long r;
	long long sum;
	long long lazy;
}tree[ 114514 * 4 ];
 
void build_tree( int id , int l , int r ) {
	tree[id].l = l;
	tree[id].r = r;
	long long mid = ( l + r ) >> 1;
	if ( l == r ) {
		tree[id].sum = num[l];
		return;
	}
	build_tree( lid , l , mid );
	build_tree( rid , mid + 1 , r );
	tree[id].sum = tree[lid].sum + tree[rid].sum;
	return;
}

inline void pushdown( int id ) {
	if ( tree[id].lazy ) {
		//存在之前的标记 
		tree[lid].lazy += tree[id].lazy;
		tree[rid].lazy += tree[id].lazy;
		tree[lid].sum += tree[id].lazy * ( tree[lid].r - tree[lid].l + 1 );
		tree[rid].sum += tree[id].lazy * ( tree[rid].r - tree[rid].l + 1 );
		tree[id].lazy = 0;//别忘了清零捏~( ̄▽ ̄)~* 
	}
	return;
}

void add_tree( int id , long long l , long long r , long long add_num ) {
	if ( tree[id].l >= l && tree[id].r <= r ) {
		//若在区间内,则直接加上add_num 
		tree[id].sum += add_num * ( tree[id].r - tree[id].l + 1 );
		tree[id].lazy += add_num;
		//这里是+= 不要写成等于,别问我怎么知道的呜呜呜 ┭┮﹏┭┮ 
		return;
	}
	pushdown( id );//防止之前有lazy却没有随着这次传下去 
	long long mid = ( tree[id].l + tree[id].r ) >> 1;
	if ( l <= mid ) add_tree( lid , l , r , add_num );
	if ( r > mid ) add_tree( rid , l , r , add_num );//传lazy 
	//因为要更新的数是l到r的,所以范围要在l和r里面 
	tree[id].sum = tree[lid].sum + tree[rid].sum;
	//随着lid与rid更新id的sum 
	return;
}

long long query_tree( int id , long long l , long long r ) {
	if ( tree[id].l >= l && tree[id].r <= r) {
		return tree[id].sum;
		//若在区间内,因为在父亲节点已经更新了id的sum
		//直接返回 
	}
	pushdown( id );
	//若l和r不在tree[id]的区间内,则下传lazy 
	long long ans = 0;
	long long mid = ( tree[id].l + tree[id].r ) >> 1;
	if ( l <= mid ) ans += query_tree( lid , l , r );
	if ( mid < r ) ans += query_tree( rid , l , r );
	return ans;
}

int main() {
	scanf("%lld",&n);
	for (int i = 1; i <= n; ++i) {
		scanf("%lld",&num[i]);
	}
	if ( n != 0 ) build_tree( 1 , 1 , n );
	scanf("%lld",&m);
	for (int i = 1; i <= m; ++i) {
		cin>>ope;
		if ( ope == "ADD" ){
			scanf("%lld%lld%lld",&a,&b,&c);
			add_tree( 1 , a , b , c );
		}
		else {
			scanf("%lld%lld",&a,&b);
			printf( "%lld\n" , query_tree( 1 , a , b ) );
		}
	}
	return 0;
}
posted @ 2023-02-10 11:06  觉清风  阅读(16)  评论(1编辑  收藏  举报