线段树模板

#include 
#include 
#include 

using namespace std;

typedef long long LL;
const int maxn=1e5+7;

int a[maxn],tree[maxn*4];
int lz[maxn*4];

void build(int node ,int start, int endd)
{
    if(start == endd)//叶子节点
    {
        tree[node] = a[start];
        return ;
    }
    else{
        int mid  = start + ((endd - start) >> 1);
        int lson = node << 1 ;//左儿子:2 * node
        int rson = (node << 1) | 1;//右儿子:2 * node + 1
        build(lson, start, mid);
        build(rson, mid+1, endd);
        tree[node] = tree[lson] + tree[rson];
    }
}

//单点更新,idx为需要更新的叶子节点编号,add为更改值
void update(int node, int start, int endd, int idx, int instead)
{
    if(start == endd)
    {
        tree[start] = instead;
        return ;
    }
    else
    {
        int mid  = start + (endd - start) >> 1;
        int lson = (node << 1);
        int rson = (node << 1) | 1;
        if( idx <= mid)
        {
            update(lson, start, mid, idx, instead);
        }
        else
        {
            update(rson, mid+1, endd, idx, instead);
        }
        tree[node] = tree[lson] + tree[rson];
    }
}


//单点查询

LL query(LL node,LL l,LL r,LL x)
{
	if(l==r&&l==x) return tree[num];
	LL mid=(l+r)>>1,tmp;
	if(x<=mid) tmp=query(num*2,l,mid,x);
	else tmp=query(num*2+1,mid+1,r,x);
	return tmp+tree[num];
}

LL query(int node, int start, int endd, int l, int r)
{
    LL sum=0;
    if(l>endd || r=endd)
    {
        return tree[node];
    }
    int mid  = start + (endd - start) >> 1;
    int lson =  node << 1;
    int rson = (node << 1) | 1;
    LL sum_left  = query(lson, start, mid,  l, r);
    LL sum_right = query(rson, mid+1, endd, l, r);
    sum = sum_left + sum_right;

    return sum;
}

------------------------------------------------------------------------------

//区间加值
void push_up(int node)
{
    tree[node] = tree[node<<1] + tree[(node<<1)|1];
}

void push_down(int node, int l, int r)
{
    int lson = (node << 1);
    int rson = (node << 1) | 1;
    if(lz[node])
    {
        lz[lson]   =  lz[node];
        lz[rson]   =  lz[node];
        int mid    =  l + (r - l) >> 1;
        tree[lson] += lz[node] * (mid-l+1);
        tree[rson] += lz[node] * (r-mid);

        lz[node]   =  0; //lazy标记使用完后需清零

    }
}

void update(int node, int start, int endd, int l, int r, int add)
{
    if(l<=start && r>=endd)//当前结点被所查询的区间覆盖
    {
        lz[node]   += add; //更新该结点所需的更新信息
        tree[node] += add * (r-l+1);//更新该结点信息
        return ;   //lazy只需记录到当前结点
    }

    push_down(node, start, endd);
    int mid = start + ((endd - start)>>1);int mid = l + ((r-l)>>1);
    if(l <= mid) update( node<<1, start, mid, l, r, add);
    if(r >= mid) update( (node<<1)|1, mid+1, endd, l, r, add);
    push_up(node);//向上递归时需一步一步更新回父节点

}

LL query(int node, int start, int endd, int l, int r)
{
    if(l <= start && r>=endd)
    {
        return tree[node];
    }
    push_down(node, start, endd);
    int mid = start + ((endd - start)>>1);
    LL ans = 0;
    if(l <= mid)   ans += query( node<<1, start, mid, l, r);
    if(r >= mid+1) ans += query( node<<1|1, mid+1, endd, l, r);

    return ans;
}

------------------------------------------------------------------------------

//区间改值

void pushup(int node)
{
    tree[node] = tree[node<<1] + tree[node<<1|1];
}

void pushdown(int node, int start, int endd)
{
    if(lz[node])
    {
        int c = lz[node];
        lz[node<<1]   = c;
        lz[node<<1|1] = c;
        int mid = start + ((endd - start)>>1);
        tree[node<<1] = (mid-start+1) * c;
        tree[node<<1] = (endd-mid) * c;
        lz[node] = 0;
    }
}

void update(int node, int start, int endd, int l, int r,int c)
{
    if(l <= start && r >= endd)
    {
        lz[node] = c;
        tree[node] = (endd-start+1) * c;
        return ;
    }
    pushdown(node, start, endd);
    int mid = start + ((endd - start)>>1);
    if(l <= mid) update(node<<1, start, mid, l, r, c);
    if(r >= mid+1) update(node<<1|1, mid+1, endd, l, r,c);
    pushup(node);
}

LL query(int node, int start, int endd, int l, int r)
{
    if(l <= start && r >= endd)
    {
        return tree[node];
    }
    pushdown(node, start, endd);
    int mid = start + ((endd-start)>>1);
    LL ans=0;
    if(l <= mid) ans+=query(node<<1, start, mid, l, r);
    if(r >= mid+1) ans+=query(node<<1|1, mid+1, endd, l, r);
    return ans;
}

int main()
{
    int q=1;
    for(int i=1;i<=6;i++)
    {
        a[i]=q++;
    }
    build(1,1,6);
    for(int i=1;i<=15;i++)
    {
        printf("tree[%d]:%d\n",i,tree[i]);
    }
    return 0;
}
--------------------------------------------------------------------------------------
//求区间最大值

void update(int o,int l,int r,int ind,int ans){  //o、l、r为当前更新到的结点、左右端点,ind为需要修改的叶子结点左端点,ans为需要修改成的值;
    if(l==r){                      //若当前更新点的左右端点相等即到叶子结点时,直接更新信息并返回
        st[o]=ans;
        return;
    }
    int m=l+((r-l)>>1);
    if(ind<=m){                      //若需要更新的叶子结点在当前结点的左儿子结点的范围内,则递归更新左儿子结点,否则更新右儿子结点
        update(o<<1,l,m,ind,ans);
    }
    else{
        update((o<<1)|1,m+1,r,ind,ans);
    }
    st[o]=max(st[o<<1],st[(o<<1)|1]);//递归回之后用儿子结点更新父节点(此处是区间最大值)
}

{                               //在main函数中的语句
        update(1,1,n,ind,ans);
}

int query(int o,int l,int r,int ql,int qr){      //ql、qr为需要查询的区间左右端点
    if(ql>r||qr=r) return st[o];        //若当前结点的区间被需要查询的区间覆盖,则返回当前结点的信息
    int m=l+((r-l)>>1);
    int p1=query(o<<1,l,m,ql,qr),p2=query((o<<1)|1,m+1,r,ql,qr);  //p1为查询左儿子结点得到的信息,p2为查询右儿子结点得到的信息
    return max(p1,p2);    //综合两个儿子结点的信息并返回
}

{    //main函数中的语句
        printf("%d\n",query(1,1,n,a,b));
}

 

转载于:https://www.cnblogs.com/orangeko/p/11367807.html

你可能感兴趣的:(线段树模板)