线段树最全模板

一定要做的线段树习题汇总

一、模板

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

#define MAXN 200010
#define lson l,mid,p<<1
#define rson mid+1,r,p<<1|1
int sum[MAXN<<2];

void pushUp(int p)
{
    sum[p]=max(sum[p<<1],sum[p<<1|1]);
}
void build(int l,int r,int p)
{
    if(l==r){
        scanf("%d",&sum[p]);
        return ;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
    pushUp(p);
}
int query(int l,int r,int p,int a,int b)
{
    if(l>=a&&b>=r)                             //根据功能代码修改部分
        return sum[p];

    int ans=0;
    int mid=(l+r)>>1;
    if(mid>=a)
        ans=max(ans,query(lson,a,b));	      //根据功能代码修改部分
    if(mid<b)
        ans=max(ans,query(rson,a,b));
    return ans;
}
void update(int l,int r,int p,int a,int b)
{
    if(l==r){                                
                                                //根据功能代码修改部分
sum[p]=b; return ; } int mid=(l+r)>>1; if(a<=mid) update(lson,a,b); else update(rson,a,b); pushUp(p);}int main(){ int n,m; char ch[5]; //freopen("in.txt","r",stdin); while(~scanf("%d%d",&n,&m)) { int a,b; build(1,n,1); while(m--) { scanf("%s%d%d",ch,&a,&b); if(ch[0]=='Q') printf("%d ",query(1,n,1,a,b)); else update(1,n,1,a,b); } } return 0;}


二、区间查询,无单点更新

#include <iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>

using namespace std;
const int maxn=200010;
int sum[maxn<<2];//数组开四倍

int h,w,n;

//p表示下标
void pushUp(int p)
{
    //p表示下标,赋值为两个儿子中的最大值
    sum[p]=max(sum[p<<1],sum[p<<1|1]);
}
//建树
void build(int l,int r,int p)
{
    if(l==r)//区间长度为0时结束递归
    {
        sum[p]=w;
        return ;
    }
    //否则的话,分别递归左儿子和右儿子
    int mid=(r+l)>>1;
    build(l,mid,p<<1);
    build(mid+1,r,p<<1|1);
    pushUp(p);
}
//区间查询
//线段树的最高顶点是表示所有行里面最大的宽度
int query(int l,int r,int p,int num)
{
    if(l==r)//找到了一个完全重合的区间
    {
        sum[p]-=num;//进行对应的查询操作
        return l;
    }
    int ans;
    int mid=(r+l)>>1;//下面要注意,先保存ans,然后更新值后再返回
    if(sum[p<<1]>=num)
    {
        ans=query(l,mid,p<<1,num);
    }
    else
    {


        ans=query(mid+1,r,p<<1|1,num);
    }
    pushUp(p);
    return ans;

}
int main()
{
    while(scanf("%d%d%d",&h,&w,&n)!=EOF)
    {
        
    memset(sum,0,sizeof(sum));
    if(h>n)h=n;
    int temp;
    build(1,h,1);//建树区间为[1,h],下标开始序号为1
    for(int i=0;i<n;i++)
    {
        scanf("%d",&temp);
        if(sum[1]<temp)
            cout<<"-1"<<endl;
        else
            cout<<query(1,h,1,temp)<<endl;
    }
    }
    return 0;
}



三、单点更新+区间求和

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

#define MAXN 50010
#define lson l,mid,p<<1
#define rson mid+1,r,p<<1|1
#define mem(a) memset(a,0,sizeof(a[0]))
int sum[MAXN<<2];

void pushUp(int p)
{
    sum[p]=sum[p<<1]+sum[p<<1|1];
}
void build(int l,int r,int p)
{
    if(l==r){
        scanf("%d",&sum[p]);
        return;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
    pushUp(p);
}
int query(int l,int r,int p,int i,int j)
{
    if(l>=i&&r<=j){
        return sum[p];
    }
    int ans=0;
    int mid=(l+r)>>1;
    if(mid<j) ans+=query(rson,i,j);
    if(mid>=i) ans+=query(lson,i,j);
    return ans;
}
void update(int l,int r,int p,int i,int j)
{
    if(l==r){
        sum[p]+=j;
        return ;
    }

    int mid=(l+r)>>1;
    if(mid>=i)
        update(lson,i,j);
    else
        update(rson,i,j);
    pushUp(p);
}

int main()
{
    int n,T;
    int cases=1;
    char str[10];
    //freopen("in.txt","r",stdin);
    scanf("%d",&T);
    while(T--)
    {
        mem(sum);
        scanf("%d",&n);
        printf("Case %d:
",cases++);

        int i,j;
        build(1,n,1);
        while(scanf("%s",str)&&strcmp(str,"End"))
        {
            scanf("%d%d",&i,&j);
            if(strcmp(str,"Query")==0)
                printf("%d
",query(1,n,1,i,j));
            else if(strcmp(str,"Add")==0)
                update(1,n,1,i,j);
            else if(strcmp(str,"Sub")==0)
                update(1,n,1,i,-j);
        }
    }
    return 0;
}


四、区间查询最值+单点更新

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

#define MAXN 200010
#define lson l,mid,p<<1
#define rson mid+1,r,p<<1|1
int sum[MAXN<<2];

void pushUp(int p)
{
    sum[p]=max(sum[p<<1],sum[p<<1|1]);
}
void build(int l,int r,int p)
{
    if(l==r){
        scanf("%d",&sum[p]);
        return ;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
    pushUp(p);
}
int query(int l,int r,int p,int a,int b)
{
    if(l>=a&&b>=r)
        return sum[p];

    int ans=0;
    int mid=(l+r)>>1;
    if(mid>=a)
        ans=max(ans,query(lson,a,b));
    if(mid<b)
        ans=max(ans,query(rson,a,b));
    return ans;
}
void update(int l,int r,int p,int a,int b)
{
    if(l==r){
        sum[p]=b;
        return ;
    }
    int mid=(l+r)>>1;
    if(a<=mid) update(lson,a,b);
    else update(rson,a,b);
    pushUp(p);
}

int main()
{
    int n,m;
    char ch[5];
    //freopen("in.txt","r",stdin);
    while(~scanf("%d%d",&n,&m))
    {
        int a,b;
        build(1,n,1);
        while(m--)
        {
            scanf("%s%d%d",ch,&a,&b);
            if(ch[0]=='Q')
                printf("%d
",query(1,n,1,a,b));
            else
                update(1,n,1,a,b);
        }
    }
    return 0;
}



原文地址:https://www.cnblogs.com/bryce1010/p/9387102.html