【NOIp复习】数据结构之线段树

本文介绍了线段树这一数据结构,用于解决区间最大最小值、区间和的查询与修改问题。通过懒惰标记思想优化了区间修改操作,并给出了相关练习题目供读者实践。
摘要由CSDN通过智能技术生成

线段树

  • 会用到的公式:将完全二叉树从左到右、从上到下依次编号,设当前结点编号为n
  • 左节点编号为:2*n 右节点编号为2*n+1
  • 把空节点的编号初始化为-1
  • 线段树的本质其实是二叉搜索树啦,所以说可以很方便的解决区间最大最小、查询区间和、修改区间和的问题
  • 用数组表示线段树的话,如果本身的区间长度为n,线段树节点数2*n左右,开3*n的大小很保险
  • 设线段树上节点代表区间为[a,b],那么左子树代表[a,(a+b)/2],右子树代表[(a+b)/2,b]
  • 如果a==b,那么该节点为叶子结点,否则递归建树

先写了个很难看的代码…(并不能作为模板,模板在后面)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define maxn 50010
#define REP(a,b) for(int i=a;i<=b;i++) 
using namespace std;

struct node{
    int left,right,val;//左右端点(代表该节点覆盖线段范围)、权值 
}tree[maxn*3];

int s[maxn];//这里的s是读入的待建树数组
int ans=0;//查询的区间和累加在ans上,注意每次查询之后都要重置ans为0

void create(int l, int r, int num){
  //建树操作,左右端点与节点编号作为传入参数 
    tree[num].left=l;
    tree[num].right=r;
    if(l==r) {
        tree[num].val=s[l]; return;
    }
    else {
        create(l,(l+r)/2,num*2);
        create((l+r)/2+
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值