线段数求和模板

/*

上次实现了线段树上的求组区间最大值操作,现在来实现求区间和的操作,其实代码兵没哟修改多少

同理,拿走的童鞋请点个赞,谢谢

本文章是个人作品,可以转载,因为你知道的太多了,如果你心情好,带上地址吧,我叫WilliamCode

*/

#include<iostream>

#include<string.h>

#include<stdio.h>

#define lson id*2    //id的左子树编号

#define rson id*2+1    //id的右子树编号

using namespace std;

int ans;

//id是每个所在区间的编号

//l和r是id所代表区间的左右节点


int tre[2000700];

int a,b,c,d,n,m,k;

int push(int id)

{

    tre[id]=tre[lson]+tre[rson];//把子叶的值拿来更新父亲节点的值

    return 0;

}



int build(int id,int l,int r)   //树的初始化,必须的操作,虽然我也不知道为什么,好像是为了给每个点编号

{

    if (l>r)    return 0;//去除非法状态,以下每个子函数都要写

    if (l==r)

                {

                tre[id]=0;

                return 0;


                }

    int mid=(l+r)/2;

    build(lson,l,mid);//递归左右子树

    build(rson,mid+1,r);//注意是mid+1

    push(id);

}

int add(int id,int l,int r,int pos,int num)     //在编号为id的区间【l,r】中,在pos位置插入num

{

    if(l>r) return 0;//判断非法状态

    if (l==r && r==pos)     //如果到了最后一层,更新值,记得return掉

        {

        tre[id]+=num;

        return 0;

        }

    int mid=(l+r)/2;

    if (pos<=mid)//如果pos在当前区间中点的左边,则在左子树中递归,反之在右子树中递归

        {

            add(lson,l,mid,pos,num);

        }

    if (pos>=mid+1)

        {

        add(rson,mid+1,r,pos,num);

        }

    push(id);//下一层递归完成后对本层进行更新

}

int query(int id,int l,int r,int L,int R)

{

    if (l>r || L>R)    return 0; //非法状态

    if (l>=L && r<=R)

        {

        ans+=tre[id];

        return 0;//一定记得return,都则id会大的飞起

        }

    int mid=(l+r)/2;

    if (L<=mid)    //如果所查询区间和【l,r】的左半边有重合,则递归求左半边,右半边同理

        {

        query(lson,l,mid,L,R);

        }

    if (mid+1<=R)

        {

        query(rson,mid+1,r,L,R);

        }

    return 0;

}

int main()

{


/******************

使用方法

1,初始化: build(1,1,maxx) maxx是所开数组的长度或者题目要求的长度

2,给节点加值 add(1,1,maxx,pos,num)  pos是位置,num是数值

3,查询区间[L,R]的和   query(1,1,maxx,L,R)

******************/

build(1,1,1000);

int n,m,a,b;


cin>>n>>m;

for (int i=1;i<=n;i++)

        {

        scanf("%d%d",&a,&b);

        add(1,1,m,a,b);

        }

for (int i=1;i<=m;i++)

        {

        scanf("%d%d",&a,&b);

        ans=0;

        query(1,1,m,a,b);

        cout<<ans<<endl;

        }

}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值