线段树常见套路

5 篇文章 0 订阅

线段树就是一颗二叉树,

在二叉树上建立区间;

所以第一个板子是如何建立一颗树,我喜欢直接建,比较暴力;

宏定义虽然慢,但是很方便;

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
PS:宏实际是调用文本,所以宏定义中的字母变量必须到时候与函数中的调用字母一致,不然会报错

<strong>void Build(int l,int r,int rt)
{
    if(l==r)
    {
        scanf("%d",&MAX[rt]);
        return;
    }
    int m=(l+r)>>1;
    Build(lson);
    Build(rson);
}</strong>


单节点更新:既将某坐标的值修改为某个值;

<strong>void Update(int p,int add,int l,int r,int rt)
{
    if(l==r)
    {
        MAX[rt]=add;
        return;
    }
    int mid=(l+r)>>1;
    if(p<=mid)
        Update(p,add,lson);
    else
        Update(p,add,rson);
    
    MAX[rt]=max(MAX[rt<<1],MAX[rt<<1|1]);
}
</strong>


最大值查询

<strong>void Build(int l,int r,int rt)//*一颗最大值树
{
    if(l==r)
    {
        scanf("%d",&MAX[rt]);
        return;
    }
    int m=(l+r)>>1;
    Build(lson);
    Build(rson);
    MAX[rt]=max(MAX[rt<<1],MAX[rt<<1|1]);
}

int Query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r)
        return MAX[rt];
    int m=(l+r)>>1;
    int ret=0;
    if(L<=m)   ret=max(ret,Query(L,R,lson));
    if(R>m)    ret=max(ret,Query(L,R,rson));
    return ret;
}</strong>



最小值查询

<strong>void Build(int l,int r,int rt)//* 一颗最小值树
{
    if(l==r)
    {
        scanf("%d",&MAX[rt]);
        return;
    }
    int m=(l+r)>>1;
    Build(lson);
    Build(rson);
    MAX[rt]=min(MAX[rt<<1],MAX[rt<<1|1]);
}
int Query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r)
        return MAX[rt];
    int m=(l+r)>>1;
    int ret=0;
    if(L<=m)   ret=min(ret,Query(L,R,lson));
    if(R>m)    ret=min(ret,Query(L,R,rson));
    return ret;
}
</strong>


查询区间和

要更新区间和,就必须把当前值储存起来,其中可以用黑科技 inline 函数

#include <bits/stdc++.h> 
using namespace std ;
#define N 500005 
#define lson l,m,rt<<1  
#define rson m+1,r,rt<<1|1  

int sum[N<<2];

inline void PushPlus(int rt)
{
	sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}

void build(int l, int r, int rt)  
{  
    if(l == r)  
   {  
        scanf("%d", &sum[rt]);  
        return ;  
   }  
    int m = ( l + r )>>1;  
  
   build(lson);  
    build(rson);  
   PushPlus(rt);  
}  
int search(int L ,int R ,int l , int r , int rt)
{
	int ans = 0 ;	
	if(L<=l&&R>=r)
	{
		return sum[rt];
	}
	int m = (l+r)>>1;
	if(L<=m) ans += search(L,R,lson);
	if(R>m) ans += search(L,R,rson);
	return ans ;
}


动态更新区间点

#define lson l , m , rt << 1  
#define rson m + 1 , r , rt << 1 | 1 
#define root 1 , N , 1 
#define LL long long  
const int maxn = 111111;  
LL add[maxn<<2];  
LL sum[maxn<<2];  
void PushUp(int rt) {  
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];  
}  
void PushDown(int rt,int m) {  
    if (add[rt]) {  
        add[rt<<1] += add[rt];  
        add[rt<<1|1] += add[rt];  
        sum[rt<<1] += add[rt] * (m - (m >> 1));  
        sum[rt<<1|1] += add[rt] * (m >> 1);  
        add[rt] = 0;  
    }  
}  
void build(int l,int r,int rt) {  
    add[rt] = 0;  
    if (l == r) {  
        scanf("%lld",&sum[rt]);  
        return ;  
    }  
    int m = (l + r) >> 1;  
    build(lson);  
    build(rson);  
    PushUp(rt);  
}  
void update(int L,int R,int c,int l,int r,int rt) {  
    if (L <= l && r <= R) {  
        add[rt] += c;  
        sum[rt] += (LL)c * (r - l + 1);  
        return ;  
    }  
    PushDown(rt , r - l + 1);  
    int m = (l + r) >> 1;  
    if (L <= m) update(L , R , c , lson);  
    if (m < R) update(L , R , c , rson);  
    PushUp(rt);  
}  




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kelisita

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值