[POJ]3264 Balanced Lineup

[POJ]3264 Balanced Lineup

问题

Description

For the daily milking, Farmer John’s N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer John decides to organize a game of Ultimate Frisbee with some of the cows. To keep things simple, he will take a contiguous range of cows from the milking lineup to play the game. However, for all the cows to have fun they should not differ too much in height.
Farmer John has made a list of Q (1 ≤ Q ≤ 200,000) potential groups of cows and their heights (1 ≤ height ≤ 1,000,000). For each group, he wants your help to determine the difference in height between the shortest and the tallest cow in the group.

Input

Line 1: Two space-separated integers, N and Q.
Lines 2..N+1: Line i+1 contains a single integer that is the height of cow i
Lines N+2..N+Q+1: Two integers A and B (1 ≤ A ≤ B ≤ N), representing the range of cows from A to B inclusive.

Output

Lines 1..Q: Each line contains a single integer that is a response to a reply and indicates the difference in height between the tallest and shortest cow in the range.

Sample Input

6 3
1
7
3
4
2
5
1 5
4 6
2 2

Sample Output

6
3
0

分析

题目大意是一个农夫有好多奶牛,假设这些奶牛已经排好队了而且还编了号,现在这个农夫很无聊就想玩个游戏,算算连续编号内的奶牛的最大身高差,真够闲的。。大概好像是这个意思。
属于RMQ问题。解法有三种,1)朴素法; 2)线段树; 3)ST
其中朴素法耗时过长,没有通过 T_T
采用了线段树法。以题中数据为例,可以构建如下图的树:
线段树
叶子节点即为输入的数据,非叶子结点保存中间的最大值与最小值,这样做在搜索时可以保证不需要每次都遍历到根节点,在大数据查找时可以大大降低复杂度。
如输入2,5。查找从根节点开始,(2,5)划分为(2,3),(4,5)两个区间,(2,3)又可以划分为(2,2),(3,3)两个区间,分别得到最大值为7,最小值为3;(4,5)直接在节点6中得到区间最大值为4,最小值为2。因此(2,5)最大值为7,最小值为2,差值为5

源代码

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

struct node
{
    int max, min, l, r;
};
node tree[200000];
int h[50005];
int m_max, m_min;

void init(int l, int r, int root)
{
    tree[root].l = l;
    tree[root].r = r;
    if (l == r)
    {
        tree[root].max = h[l];
        tree[root].min = h[l];
        return;
    }
    int mid = (l + r) >> 1;
    init(l, mid, root * 2);
    init(mid + 1, r, root * 2 + 1);
    tree[root].max = max(tree[2 * root].max, tree[2 * root + 1].max);
    tree[root].min = min(tree[2 * root].min, tree[2 * root + 1].min);
}

void findit(int l, int r, int root)
{
    if (tree[root].l == l && tree[root].r == r)
    {
        m_max = max(m_max, tree[root].max);
        m_min = min(m_min, tree[root].min);
        return;
    }
    int mid = (tree[root].l + tree[root].r) >> 1;
    if (mid >= r)
        findit(l, r, root * 2);
    else if (mid<l)
        findit(l, r, root * 2 + 1);
    else
    {
        findit(l, mid, root * 2);
        findit(mid + 1, r, root * 2 + 1);
    }
}

int main()
{
    int N, Q, x, y;
    scanf("%d%d", &N, &Q);
    for (int i = 1; i <= N; i++)
        scanf("%d", &h[i]);
    init(1, N, 1);
    while (Q--)
    {
        m_max = 0;
        m_min = 99999999;
        scanf("%d%d", &x, &y);
        findit(x, y, 1);
        printf("%d\n", m_max - m_min);
    }
    return 0;
}

程序结果

ResultMemoryTimeLanguageCode Length
Accepted2400K1750MSC++1175B

还是好久 T_T, 被第一名 250MS的大神甩出不知道多少条街。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值