线段树简化

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<string>
using namespace std;
const int MaxN = 1e6 + 5;
//线段树的基础操作5个:
//1.建树
//2.单点查询(转换成区间查询做)
//3.单点修改(转换成区间修改做)
//4.区间查询
//5.区间修改
int x;//单点查询和修改时为目标位置,区间查询时为查询的左端点
int y;//查询的右端点
int ans;//查询结果
int val;//区间修改的值
struct node
{//数据结构
	int l, r, w, f;
	//l, r分别表示区间左右端点,w表示区间和
	}tree[4*MaxN];//记得要开4倍空间
void build(int l, int r, int k)//左端点,右端点,当前端点ps:build(1,n,1);
{//建树
	tree[k].l = l;
	tree[k].r = r;
	if(tree[k].l == tree[k].r)//叶子节点
	{
		scanf("%d", &tree[k].w);
		return ;
		}
	int mid = (l + r) / 2;
	build(l, mid, k * 2);//左孩子
	build(mid + 1, r, k * 2 + 1);//右孩子
	tree[k].w = tree[k * 2].w + tree[k * 2 + 1].w;
	//状态合并,此节点的w=两个孩子的w之和
	}
void down(int k)
{//懒标记下传
	tree[k * 2].f += tree[k].f;
	tree[k * 2 + 1].f += tree[k].f;
	tree[k * 2].w += tree[k].f * (tree[k * 2].r - tree[k * 2].l + 1);
	tree[k * 2 + 1].w += tree[k].f * (tree[k * 2 + 1].r - tree[k * 2 + 1]. l + 1);
	tree[k].f = 0;
	}
void add_sum(int k)
{//区间修改
	if(tree[k].l >= x && tree[k].r <= y)
	{//当前区间全部对要修改的区间有用
		tree[k].w += (tree[k].r - tree[k].l + 1) * val;
		tree[k].f += val;
		return ;
		}
	if(tree[k].f) down(k);
	//懒标记下传,只有不满足上面的if条件才执行
	//所以一定会用到当前节点的子节点
	int mid = (tree[k].l + tree[k].r) / 2;
	if(x <= mid) add_sum(k * 2);
	if(y > mid) add_sum(k * 2 + 1);
	tree[k].w = tree[k * 2].w + tree[k * 2 + 1].w;//要修改区间状态
	}
void sum(int k)
{//区间查询
	if(tree[k].l >= x && tree[k].r <= y)
	{
		ans = ans + tree[k].w;
		return ;
		}
	if(tree[k].f) down(k);
	int mid = (tree[k].l + tree[k].r) / 2;
	if(x <= mid) sum(k * 2);
	if(y > mid) sum(k * 2 + 1);
	}

int main()
{
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值