线段树基础

线段树:线段树用来储存区域信息

主要有五种操作:

建树、单点查询、单点修改、区间查询、区间修改。

注意和树状数组一样不能处理位置0

#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define inf 0x3f3f3f3f
#define lson l,m,pos<<1
#define rson m+1,r,pos<<1|1
const int N=100000+2;
ll sum[N<<2],col[N<<2];
void up(int pos)
{
    sum[pos]=sum[pos<<1]+sum[pos<<1|1];
}
void down(int pos,int m)
{
    if(col[pos])
    {
        col[pos<<1]+=col[pos];
        col[pos<<1|1]+=col[pos];
        sum[pos<<1]+=col[pos]*(m-(m>>1));
        sum[pos<<1|1]+=col[pos]*(m>>1);
        col[pos]=0;
    }
}

void build(int l,int r,int pos)
{
    col[pos]=0;
    if(l==r)
    {
        scanf("%lld",&sum[pos]);
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    up(pos);
}
void update(int L,int R,int v,int l,int r,int pos)
{
    if(L<=l&&r<=R)
    {
        sum[pos]+=(r-l+1)*v;
        col[pos]+=v;
        return ;
    }
    down(pos,r-l+1);
    int m=(l+r)>>1;
    if(L<=m)update(L,R,v,lson);
    if(R>m)update(L,R,v,rson);
    up(pos);
}
ll query(int L,int R,int l,int r,int pos)
{
    if(L<=l&&r<=R)
    {
        return sum[pos];
    }
    down(pos,r-l+1);
    ll ans=0;
    int m=(l+r)>>1;
    if(L<=m)ans+=query(L,R,lson);
    if(R>m)ans+=query(L,R,rson);
    return ans;
}
View Code
原文地址:https://www.cnblogs.com/bxd123/p/10356042.html