线段树2

#include<bits/stdc++.h>

using namespace std;

#define root 1,n,1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

const int maxn=100010;

int n,m,a[maxn];

struct node//一个线段树节点 
{//第一个要修改的地方:要维护的东西 
	int sum;//代表区间和
	int minv;//代表区间最小值
	int maxv;//代表区间最大值 
	int size;//代表区间长度 
	int add;//这段区间被整体加了多少
	node()
	{
		sum = size = add = minv = maxv = 0;
	} 
	void init(int v)//用一个数初始化 
	{//第二个修改的地方:怎么用一个数初始化 
		sum = minv = maxv = v;
		size = 1;
	}
}z[maxn<<2];//z[i]就代表线段树的第i个节点 

node operator+(const node &l,const node &r)
{//第三个需要修改的地方:左右儿子怎么合并 
	node res;
	
	res.sum = l.sum + r.sum;
	res.size = l.size + r.size;
	res.minv = min(l.minv, r.minv);
	res.maxv = max(l.maxv, r.maxv);
	
	return res;
}

void color(int l,int r,int rt,int v)//给l,r,rt这个节点打一个+v的懒标记
{//第四个需要修改的地方:怎么打标记 
	z[rt].add += v;
	z[rt].sum += z[rt].size * v;
	z[rt].minv += v;
	z[rt].maxv += v;
} 

void push_col(int l,int r,int rt)//标记下放 把标记告诉儿子
{
	if (z[rt].add == 0) return; //没标记 不需要下放  可以不要这句话 但会慢些 
	int m=(l+r)>>1;
	color(lson,z[rt].add);
	color(rson,z[rt].add);
	z[rt].add=0;
} 

void build(int l,int r,int rt)//建树 初始化l,r,rt这个节点 
//编号为rt的线段树节点 所对应的区间是l~r 
{
	if (l==r)
	{
		z[rt].init(a[l]);
		return;
	} 
	int m=(l+r) >> 1;
	build(lson);
	build(rson);
	z[rt] = z[rt<<1] + z[rt<<1|1]; 
}

node query(int l,int r,int rt,int nowl,int nowr)
//l,r,rt描述了一个线段树节点
//nowl nowr代表了询问的区间的左端点和右端点 
{
	if (nowl <= l && r <= nowr) return z[rt];
	push_col(l,r,rt);
	int m=(l+r)>>1;
	if (nowl<=m)
	{
		if (m<nowr) return query(lson,nowl,nowr) + query(rson,nowl,nowr);
		else return query(lson,nowl,nowr);
	}
	else return query(rson,nowl,nowr);
}

void modify(int l,int r,int rt,int nowl,int nowr,int v)
//把nowl~nowr这段区间全部整体+v 
{
	if (nowl<=l && r<=nowr)//当前线段树节点被修改区间整体包含
	{
		color(l,r,rt,v);//给l,r,rt这个节点打一个+v的懒标记
		return; 
	} 
	push_col(l,r,rt);
	int m=(l+r)>>1;
	if (nowl<=m) modify(lson,nowl,nowr,v);
	if (m<nowr) modify(rson,nowl,nowr,v);
	z[rt] = z[rt<<1] + z[rt<<1|1];
}

int main()
{
	cin >> n;
	for (int i=1;i<=n;i++)
		cin >> a[i];
	build(root);
	cin >> m;
	for (int i=1;i<=m;i++)
	{
		int opt;
		cin >> opt;
		if (opt==1)//询问
		{
			int l,r;
			cin >> l >> r;
			cout << query(root,l,r).sum << "\n";
		} 
		else
		{
			int l,r,v;
			cin >> l >> r >> v;
			modify(root,l,r,v);
		}
	}
		
	return 0;
}
posted @ 2025-06-21 20:38  Fire_poetry  阅读(3)  评论(0)    收藏  举报