poj3264

每天挤奶,农夫约翰的N奶牛(1≤)N≤50,000)总是按照相同的顺序排列。有一天,农夫约翰决定和一些奶牛一起组织一场终极飞盘比赛。为了保持简单,他将从挤奶阵容中拿出一系列连续的奶牛来玩游戏。然而,为了让所有的牛都有乐趣,它们不应该在高度上有太大的差异。

农夫约翰列出了一份清单Q(1≤)Q(≤200,000)潜在群牛及其高度(1≤)高度≤1,000,000)。对于每一组,他需要你的帮助,以确定最小和最高的母牛之间的身高差异。

输入
第1行:两个空格分隔的整数,N和Q.
第2行.。N+1:一行i+1包含一个整数,即牛的高度。i
线N+2… N+ Q+1:两个整数A和B(1≤)A ≤ B ≤ N),表示从A到B包括在内。
输出量
第1行.。Q每一行包含一个整数,它是对答复的响应,并指示范围内最高的奶牛和最短的奶牛之间的高度差异。
样本输入
6 3
1
7
3
4
2
5
1 5
4 6
2 2
样本输出
6
3
0
题目大意:给定n,q分别表示区间的大小为:n,后跟着q次查询;求得给定区间最大值与最小值之差,
代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int INF=0xffffff0;     //确定一个最大值
const int maxn=50010;      //n的最大值
/**结点结构*/
struct Node
{
    int L,R;
    int minV,maxV;
};

Node tree[4*maxn];        //用数组表示线段树
int a[maxn];             //存放结点数值

int maxV=-INF;
int minV=INF;      //存放最大值与最小值

/**建立线段树,并赋初值*/
void build_Tree(int root,int L,int R)
{
    tree[root].L=L;
    tree[root].R=R;
    /**到叶子结点时附值*/
    if(L==R)
    {
        tree[root].maxV=tree[root].minV=a[L];
        return ;
    }

    int mid=(tree[root].L+tree[root].R)/2;
    build_Tree(2*root,L,mid);
    build_Tree(2*root+1,mid+1,R);

    tree[root].minV=min(tree[2*root].minV,tree[2*root+1].minV);
    tree[root].maxV=max(tree[2*root].maxV,tree[2*root+1].maxV);          //当不是叶子结点时,存放左右孩子的最大值与最小值
}
/**查询区间[s,e]中的最大值与最小值*/
void  Query(int root,int s,int e)
{
    if(minV<=tree[root].minV&&maxV>=tree[root].maxV)
        return;

    /**当刚好区间相等时*/
    if(tree[root].L==s&&tree[root].R==e)
    {
        minV=min(minV,tree[root].minV);
        maxV=max(maxV,tree[root].maxV);
        return ;
    }

    int mid=(tree[root].L+tree[root].R)/2;
    /**区间过大时*/
    if(e<=mid)
        Query(2*root,s,e);
    else if(s>mid)
        Query(2*root+1,s,e);
    /**左右孩子*/
    else
    {
        Query(2*root,s,mid);
        Query(2*root+1,mid+1,e);
    }
}
int main()
{
    int n,q;
    int num;
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }

    build_Tree(1,1,n);

    int s,e;
    for(int i=1;i<=q;i++)
    {
        minV=INF;
        maxV=-INF;
        scanf("%d%d",&s,&e);
        Query(1,s,e);
        printf("%d\n",maxV-minV);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值