线段树模板

单点更新

#include"cstdio"
#include"iostream"
#include"cstring"
#include"algorithm"
using namespace std;
#define MAXN 50005
int tree[(MAXN<<2)+10];

void build(int node,int left,int right)     //建树
{
    if(left==right)
    {
        //tree[node]=1;             //初始赋值1建树 
        scanf("%d",&tree[node]);    //输入赋值建树 
    }
    else
    {
        build(node<<1,left,left+right>>1);          //构造左子树 
        build((node<<1)+1,(left+right>>1)+1,right);     //构造右子树

        //回溯时得到当前node节点的线段信息
        tree[node]=tree[node<<1]+tree[(node<<1)+1]; //求和
        //tree[node]=max(tree[node<<1],tree[(node<<1)+1]);  //求最大值
        //tree[node]=min(tree[node<<1],tree[(node<<1)+1]);  //求最小值
    }
}
void update(int node,int left,int right,int pos,int data)       //更新
{
    if(left==right)
    {
        tree[node]=data;        //赋值更新 
        //运算更新,如 tree[node]+=data;
        return;
    }
    int mid=(left+right)>>1;
    if(pos<=mid)
        update(node<<1,left,mid,pos,data);
    else
        update((node<<1)+1,mid+1,right,pos,data);
    tree[node]=tree[node<<1]+tree[(node<<1)+1]; //求和
    //tree[node]=max(tree[node<<1],tree[(node<<1)+1]);  //求最大值
    //tree[node]=min(tree[node<<1],tree[(node<<1)+1]);  //求最小值
}
int query(int node,int begin,int end,int left,int right)        //查询
{
    int p1,p2;
    if(left>end || right<begin)
        return -1;
    if(begin>=left && end<=right)
        return tree[node];
    p1=query(node<<1,begin,begin+end>>1,left,right);
    p2=query((node<<1)+1,(begin+end>>1)+1,end,left,right);
    if(p1==-1)
        return p2;
    if(p2==-1)
        return p1;
    return p1+p2;       //求和
    //return max(p1,p2);    //求最大
    //return min(p1,p2);    //求最小 
}

区间更新

#include"iostream"
#include"cstdio"
#include"cstring"
using namespace std;
const int MAXN=100000;
#define LL long long 
LL tree[(MAXN<<2)+10];
LL mark[(MAXN<<2)+10];
void build(int node,int begin,int end)  //建树
{
    mark[node]=0;//标记初始化
    if(begin==end)
    {
        scanf("%lld",&tree[node]);
    }
    else
    {
        build(2*node,begin,(begin+end)>>1);
        build(2*node+1,(begin+end>>1)+1,end);
        tree[node]=tree[node<<1]+tree[(node<<1)+1];//pushup
    }
}

void pushdown(int node,int left,int right)  //延迟更新
{
    if(mark[node])
    {
        int mid=left+right>>1;
        mark[node<<1]+=mark[node];
        mark[(node<<1)+1]+=mark[node];
        tree[node<<1]+=(mid-left+1)*mark[node];
        tree[(node<<1)+1]+=(right-mid)*mark[node];
        mark[node]=0;
    }
}
void update(int node,int begin,int end,int left,int right,LL data)  //更新
{
    if(begin>right || left>end)
        return;
    if( left<= begin && end<=right)
    {
        tree[node] += (end-begin+1)*data;
        mark[node]+=data;
        return;
    }
    pushdown(node,begin,end);
    int mid=(begin+end)>>1;
    update(node<<1,begin,mid,left,right,data);
    update((node<<1)+1,mid+1,end,left,right,data);
    tree[node]=tree[node<<1]+tree[(node<<1)+1];
}
LL query(int node,int begin,int end,int left,int right) //查询
{
    if(begin>right || left>end)
        return 0;
    if(begin>=left && end<=right)
        return tree[node];
    pushdown(node,begin,end);
    int mid=(begin+end)>>1;
    return query(node<<1,begin,mid,left,right)+query((node<<1)+1,mid+1,end,left,right);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值