线段树

用一维数组存储二叉树,利用二分查找降低效率

1.线段树的构造,区间查询

描述:
给定n(1<=n<=50000)个数,求任意区间中最大值最小值的差,

eg:
输入:
6 3
1 7 3 4 2 5 
1 5
4 6
2 2
输出:
6 
3
0
//balanced lineup  
#include<iostream>
#include<cstring>
#include<climits>
using namespace std;
const int  maxn=50001;
const int inf=INT_MAX;
#define max(a,b) a>b?a:b
#define min(a,b)  a<b?a:b
#define L(a) ((a)<<1)         //左孩子 
#define R(a) (((a)<<1)+1)     //右孩子

typedef struct node_t{
    int left,right;
    int max,min; //区间里的最大值最小值 
}node_t; 
int A[maxn];//用作输入数据 0位置未用 
/*完全二叉树 结点从1开始 层次从1开始
用一维数组存储二叉树,空间约为4*n  */
node_t node[4*maxn];  //数组存放结构体 
int minx,maxx; //存放结果 
void init(){
    memset(node,0,sizeof(node));
}
/*以t为结点,为区间A【l,r】建立线段树*/
void build(int t,int l,int r){ //懂了 
    node[t].left=l;
    node[t].right=r;
    if(l==r) {
        node[t].max=node[t].min=A[l];
        return ;
    }
    const int mid=(l+r)/2;
    build(L(t),l,mid);
    build(R(t),mid+1,r);
    node[t].max=max(node[L(t)].max,node[R(t)].max);
    node[t].min=min(node[L(t)].min,node[R(t)].min);
} 
//查询根结点为t,区间A[l,r] 的最大值最小值 
void query(int t,int l,int r){
    if(node[t].left==l&&node[t].right==r){
    if(maxx<node[t].max)  maxx=node[t].max;
    if(minx>node[t].min) minx=node[t].min;
    return ;}
    const int mid=(node[t].left+node[t].right)/2;
    if(l>mid){
        query(R(t),l,r);
    }else if(r<=mid){
        query(L(t),l,r);//
    }else {
        query(L(t),l,mid);
        query(R(t),mid+1,r);
    }
}
int main(){
    int n,q,i;
        int a,b;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>A[i];
    init();
//    cout<<"hello"<<endl; 
    build(1,1,n);
//    cout<<"hello"<<endl;
    while(cin>>a>>b){
//        cin>>a>>b;
        maxx=0;
        minx=inf;
//        cout<<"hello"<<endl;
        query(1,a,b);    //A[a,b]之间的最大最小值 
//        cout<<"helo"<<endl;
        cout<<maxx<<" "<<minx<<endl;
    } 
    return 0;
} 
View Code

2.单点更新,区间求和     未完待续

原文地址:https://www.cnblogs.com/helloworld2019/p/10496263.html