平衡的阵容Balanced Lineup 题解 线段树模板题

这一题还是比较简单的,有人说要用ST表,也可以,不过这类题最好是用线段树,因为这一题不用修改,所以可以用ST表,言归正传,怎么用线段树解决,首先要有一些基础,知道怎么用代码实现线段树的建树、修改、询问这三类,如果不清楚可以去看一下我关于讲线段树的博客。链接:https://blog.csdn.net/qq_34990731/article/details/81514622
下面讲思路,这一题要通过维护一个线段树,叶子节点存两个信息,一个是这个区间的最大值与最小值,其他的和线段树没差了,下面上代码(代码有详细注释)。

#include<iostream>
using namespace std;
int w[50000];//这个数组存每头牛的身高 
struct Node 
{
    int l,r,zx,zd;
    #define l(x) tree[x].l//这里是定义l(x)这一种写法代替 tree[x].l比较方便也可以不用不过下面代码要对应改一下 
    #define r(x) tree[x].r
    #define zd(x) tree[x].zd
    #define zx(x) tree[x].zx
}tree[50000<<2];//用结构体加数组来构造线段树,这种方式空间浪费的比较大,
//不过更简单,如果有卡内存是过不了的不过要用压缩堆或离散化,这里就不提供代码了,有兴趣的自己了解。 
int chaxunzd(int p,int l,int r)//查询没个区间的最大值 
{
    if(l<=l(p) && r>=r(p))//如果区间包括直接返回对应的最大值 
        return zd(p);
    else//没包括的话计算中间点通过目标区间的左右端点的值与中间值来用二分查找 
    {
        int lmax=0,rmax=0;
        int mid=(l(p)+r(p))>>1;
        if(l<mid)//查找左子树 
        {
            if(r>mid) //区别一下右端点到底应该是目标右端点即r还是中间点 
                lmax=chaxunzd(p<<1,l,mid);
            else    lmax=chaxunzd(p<<1,l,r);
        } 
        if(r>mid)//查找右子树 
        {
            if(l<mid)
                rmax=chaxunzd(p<<1|1,mid,r);
            else    rmax=chaxunzd(p<<1|1,l,r);
        }
        return max(lmax,rmax);//返回左子树与右子树中最大的 
    }
}
int chaxunzx(int p,int l,int r)//查找最小值与最大值一样只不过稍微改一下 
{
    if(l<=l(p) && r>=r(p))
        return zx(p);
    else
    {
        int lmin=1000000,rmin=1000000;
        int mid=(l(p)+r(p))>>1;
        if(l<mid)
        {
            if(r>mid) 
                lmin=chaxunzx(p<<1,l,mid);
            else    lmin=chaxunzx(p<<1,l,r);
        } 
        if(r>mid)
        {
            if(l<mid)
                rmin=chaxunzx(p<<1|1,mid,r);
            else    rmin=chaxunzx(p<<1|1,l,r);
        }
        return min(lmin,rmin);
    }
}
void build(int p,int l,int r)//建立一颗线段树 
{   
    l(p)=l;
    r(p)=r;
    int mid=(l+r)>>1;
    zx(p)=zd(p)=0;
    if(r-l==1)
        zx(p)=zd(p)=w[l];
    else
    {
        build(p<<1,l,mid);
        build(p<<1|1,mid,r);
        zd(p)=max(zd(p<<1),zd(p<<1|1));//p<<1相当于p*2这里用位运算是因为位运算效率(时间耗费的常数)大,这里要递归计算怕卡常数 
        zx(p)=min(zx(p<<1),zx(p<<1|1));//p<<1|1相当于p*2+1 
    }
}
int main()
{
    int n,q,i,j,zd,zx,l,r;
    cin >>n>>q;
    for(i=1;i<=n;i++)
        cin >>w[i];//读入数据 
    build(1,1,n+1);//建树 
    for(i=1;i<=q;i++)//询问 
    {
        cin >>l>>r;
        zd=chaxunzd(1,l,r+1);
        zx=chaxunzx(1,l,r+1);
        cout <<zd-zx<<endl;
    }
    return 0;
}

代码是用来参考而不是抄袭的,希望大家看完不要直接复制粘贴,而是自己打一遍,祝大家都能自己AC。

猜你喜欢

转载自blog.csdn.net/qq_34990731/article/details/81514144
今日推荐