码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 3264 -----RMQ问题

时间:2017-03-27 18:17:20      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:int   数列   ++   memory   time   namespace   source   put   sep   

Balanced Lineup

Time Limit: 5000 MS Memory Limit: 0 KB

64-bit integer IO format: %I64d , %I64u Java class name: Main

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
 
 
1.
RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大)值。也就是说,RMQ问题是指求区间最值的问题。
 
2.

首先是预处理,用动态规划(DP)解决。设A[i]是要求区间最值的数列,F[i, j]表示从第i个数起连续2^j个数中的最大值。例如数列3 2 4 5 6 8 1 2 9 7,F[1,0]表示第1个数起,长度为2^0=1的最大值,其实就是3这个数。 F[1,2]=5,F[1,3]=8,F[2,0]=2,F[2,1]=4……从这里可以看出F[i,0]其实就等于A[i]。这样,DP的状态、初值都已经有了,剩下的就是状态转移方程(关键)。我们把F[i,j]平均分成两段(因为f[i,j]一定是偶数个数字),从i到i+2^(j-1)-1为一段,i+2^(j-1)到i+2^j-1为一段(长度都为2^(j-1))。用上例说明,当i=1,j=3时就是3,2,4,5 和 6,8,1,2这两段。F[i,j]就是这两段的最大值中的最大值。于是我们得到了动态规划方程F[i, j]=max(F[i,j-1], F[i + 2^(j-1),j-1])。

然后是查询。取k=[log2(j-i+1)],则有:RMQ(A, i, j)=min{F[i,k],F[j-2^k+1,k]}。 举例说明,要求区间[2,8]的最大值,就要把它分成[2,5]和[5,8]两个区间,因为这两个区间的最大值我们可以直接由f[2,2]和f[5,2]得到。

 3 代码

#include<stdio.h>
#include<math.h>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=50005;

int d1[maxn][20];
int d2[maxn][20];
int a[maxn];
int n,m;

void RMQ_init()
{
for(int i=0;i<n;i++)
{
d1[i][0]=a[i];
d2[i][0]=a[i];
}
for(int j=1;(1<<j)<=n;j++)
for(int i=0;i+(1<<j)-1<n;i++)
{

d1[i][j]=min(d1[i][j-1],d1[i+(1<<(j-1))][j-1]);
d2[i][j]=max(d2[i][j-1],d2[i+(1<<(j-1))][j-1]);
}
}

int rmq_min(int L,int R)
{

int k=0;
while((1<<(k+1))<=R-L+1)
k++;
return min(d1[L][k],d1[R-(1<<k)+1][k]);
}
int rmq_max(int L,int R)
{

int k=0;
while((1<<(k+1))<=R-L+1)
k++;
return max(d2[L][k],d2[R-(1<<k)+1][k]);
}

int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
RMQ_init();
for(int i=0;i<m;i++)
{
int L,R;
scanf("%d%d",&L,&R);
L--,R--;
printf("%d\n",rmq_max(L,R)-rmq_min(L,R));
}

}
return 0;
}

 

 

 
 
 
 
 
 

POJ 3264 -----RMQ问题

标签:int   数列   ++   memory   time   namespace   source   put   sep   

原文地址:http://www.cnblogs.com/hhkobeww/p/6628026.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!