【算法板子】线段树模板(洛谷P3372)

题目链接:https://www.luogu.com.cn/problem/P3372

几年没打线段树了,复习一下

#include<bits/stdc++.h>

using namespace std;

/*

线段树

定长数组的区间操作

时 : O(logn)
空 : O(nlogn)

*/

typedef long long val_type;

struct Node
{
    
    
	int l,r,mid;
	val_type sum,lazy;
	/*
		l,r  : charge subscript start/end
		sum  : the sum of this sub-array
		lazy : a tag for operate (eg. each elemt should add)
	*/
};
vector<Node>node;
vector<val_type>a;
int n,k;

/*
	parameter f down there is for locate the node on accessing
*/

val_type biuld(int l=1,int r=n,int f=1)
{
    
    
	// printf("build( %d , %d , %d )\n",l,r,f);
	if(l==r)
		return (node[f]={
    
    l,r,l,a[l]}).sum;
	int mid=l+(r-l)/2;
	return (node[f]={
    
    l,r,mid,biuld(l,mid,f*2)+biuld(mid+1,r,f*2+1)}).sum;
}

val_type add(int&l,int&r,val_type&val,int f=1)
{
    
    
	// printf("add( %d , %d , %d , %d )\n",l,r,val,f);
	if(node[f].l>=l&&node[f].r<=r)
	{
    
    
		node[f].lazy+=val;
		return val*(node[f].r-node[f].l+1);
	}
	val_type ret=0;
	if(node[f].mid>=l)
		ret+=add(l,r,val,f*2);
	if(node[f].mid+1<=r)
		ret+=add(l,r,val,f*2+1);
	node[f].sum+=ret;
	return ret;
}

val_type sum(int&l,int&r,int f=1)
{
    
    
	if(node[f].lazy)
	{
    
    
		if(node[f].l!=node[f].r)
		{
    
    
			node[f*2].lazy+=node[f].lazy;
			node[f*2+1].lazy+=node[f].lazy;
		}
		node[f].sum+=node[f].lazy*(node[f].r-node[f].l+1);
		node[f].lazy=0;
	}
	if(node[f].l>=l&&node[f].r<=r)
		return node[f].sum;
	val_type ret=0;
	if(node[f].mid>=l)
		ret+=sum(l,r,f*2);
	if(node[f].mid+1<=r)
		ret+=sum(l,r,f*2+1);
	return ret;
}

void check()
{
    
    
	int cas=0;
	for(auto it:node)
		printf("%d : %d %d %lld %lld\n",cas++,it.l,it.r,it.sum,it.lazy);
}

int main()
{
    
    
	int m;
	scanf("%d%d",&n,&m);
	a.resize(n+1);
	for(int i=1;i<=n;i++)
		scanf("%lld",&a[i]);
	node.resize(log(n)/log(2)*n);
	biuld();
	// check();
	val_type k;
	for(int cas=1,op,l,r;cas<=m;cas++)
	{
    
    
		scanf("%d%d%d",&op,&l,&r);
		if(op==1)
		{
    
    
			scanf("%lld",&k);
			add(l,r,k);
		}
		else
		{
    
    
			printf("%lld\n",sum(l,r));
		}
		// check();
	}
	return 0;
}

/*
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4


*/