poj 3264(模板RMQ)

Farmer John在组织游戏时,需要确保每组奶牛之间的身高差距不大,以确保所有奶牛都能享受游戏的乐趣。通过输入奶牛数量、游戏组数及每组奶牛的身高,读者将学习如何计算每组中最高与最低奶牛之间的身高差。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Balanced Lineup
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 34488 Accepted: 16203
Case Time Limit: 2000MS

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

Source

USACO 2007 January Silver

就是套模板啦,算法训练指南第198页有详解。

AC代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int n,q;
int a[50010];
int d1[50010][110],d2[50010][110];
void RMQ_init(){
    for(int i=1;i<=n;i++)
        d1[i][0]=d2[i][0]=a[i];

    for(int j=1;(1<<j)<=n;j++)
    for(int i=1;i+(1<<j)-1<=n;i++){
        d1[i][j]=max(d1[i][j-1],d1[i+(1<<(j-1))][j-1]);
        d2[i][j]=min(d2[i][j-1],d2[i+(1<<(j-1))][j-1]);
    }
}
int RMQ1(int x,int y){
    int k=0;
    while((1<<(k+1)<=y-x+1)) k++;
    return max(d1[x][k],d1[y-(1<<k)+1][k]);
}
int RMQ2(int x,int y){
    int k=0;
    while(((1<<(k+1))<=y-x+1)) k++;
    return min(d2[x][k],d2[y-(1<<k)+1][k]);
}
int main(){
    while(scanf("%d%d",&n,&q)!=EOF){
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        RMQ_init();
        while(q--){
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%d\n",RMQ1(x,y)-RMQ2(x,y));
        }
    }
    return 0;
}


<think>嗯,用户想了解POJ 3264 Balanced Lineup的解法或讨论。首先,我需要回忆一下这道题的内容。题目应该是给定一个数列,查询区间内的最大值和最小值的差。属于RMQ问题的一种变体,因为普通的RMQ可能只查询最大或最小,但这里需要同时找到两者,然后计算差值。 接下来,用户提到参考了站内引用中的信息,里面提到了RMQ问题的解决方法,比如ST算法和线段树。根据引用中的例子,本题用的是线段树解法。但可能用户想知道不同的解法,所以需要分别介绍ST算法和线段树两种方法。 首先,ST算法适合处理静态数据,预处理时间O(n log n),查询时间O(1)。而线段树则可以处理动态更新的数据,预处理O(n),查询O(log n)。在本题中,数据是静态的,所以两种方法都适用。但题目可能更倾向于线段树解法,因为引用里明确提到。 接下来,我需要详细解释这两种方法的实现步骤。对于ST算法,需要构建两个预处理表,一个用于最大值,一个用于最小值。每个查询区间分成两个块,分别查最大和最小,然后相减。而线段树则需要构建每个节点保存区间的最大最小值,查询时递归地合并左右子区间的结果。 然后,要考虑代码实现。用户可能需要具体的代码示例。比如ST算法的预处理部分需要计算log表,填充st表。而线段树则需要构建树结构,每个节点存储区间的最大最小值,查询时递归查找左右子树。 另外,用户可能关心的优化点,比如线段树的递归与非递归实现,或者ST算法的空间优化。同时,需要注意题目的数据范围,比如数组长度和查询次数,以确定哪种方法更优。例如,如果查询次数极大,ST算法的O(1)查询会更高效。 用户可能还会遇到的一些问题,比如如何处理区间边界,或者在预处理时如何分割区间。需要指出关键点,比如在ST算法中,区间长度是2^j,而线段树中的区间分割是二分法。 最后,生成相关问题需要考虑用户可能进一步想知道的内容,比如不同解法的对比,优化方法,或者类似题目的扩展。例如,动态更新时的处理,或者二维RMQ问题等。</think>### POJ 3264 Balanced Lineup 解法分析 #### 问题描述 给定一个长度为$n$的数列$A$,处理$q$次查询,每次查询区间$[i,j]$内的**最大值与最小值之差**。这是RMQ问题的扩展,需要同时处理区间最值查询和差值计算。 --- ### 解法一:线段树 **步骤说明** 1. **建树**:构建线段树,每个节点存储区间$[l,r]$的**最大值**和**最小值**。 $$ \text{节点属性} = (\text{max\_val}, \text{min\_val}) $$ 2. **查询**:递归查询区间$[i,j]$的极值,合并左右子树结果。 3. **差值计算**:返回查询结果中的$\text{max\_val} - \text{min\_val}$。 **代码示例** ```python class SegmentTree: def __init__(self, data): self.n = len(data) self.tree = [ (0, 0) ] * (4 * self.n) self.build(0, 0, self.n-1, data) def build(self, node, l, r, data): if l == r: self.tree[node] = (data[l], data[l]) return mid = (l + r) // 2 self.build(2*node+1, l, mid, data) self.build(2*node+2, mid+1, r, data) max_val = max(self.tree[2*node+1][0], self.tree[2*node+2][0]) min_val = min(self.tree[2*node+1][1], self.tree[2*node+2][1]) self.tree[node] = (max_val, min_val) def query(self, node, l, r, ql, qr): if qr < l or ql > r: return (-float('inf'), float('inf')) if ql <= l and r <= qr: return self.tree[node] mid = (l + r) // 2 left = self.query(2*node+1, l, mid, ql, qr) right = self.query(2*node+2, mid+1, r, ql, qr) return (max(left[0], right[0]), min(left[1], right[1])) ``` --- ### 解法二:ST表(Sparse Table) **步骤说明** 1. **预处理**:构建两个ST表,分别存储区间最大值和最小值。 $$ \text{st\_max}[i][j] = \max(A[i \ldots i+2^j-1]) $$ $$ \text{st\_min}[i][j] = \min(A[i \ldots i+2^j-1]) $$ 2. **查询**:对任意区间$[i,j]$,计算区间长度$k = \lfloor \log_2(j-i+1) \rflo
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值