线段树最全模板

来源:互联网 发布:好友生日提醒软件 编辑:程序博客网 时间:2024/06/14 14:25

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

一、模板

#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|1int 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\n",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:\n",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\n",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|1int 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\n",query(1,n,1,a,b));            else                update(1,n,1,a,b);        }    }    return 0;}



原创粉丝点击