poj3264 balanced lineup

来源:互联网 发布:三恒系统 知乎 编辑:程序博客网 时间:2024/06/02 04:32
Balanced Lineup
Time Limit: 5000MS Memory Limit: 65536KTotal Submissions: 55020 Accepted: 25769Case 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 31734251 54 62 2

Sample Output

630

Source

裸的RMQ,,但是得理解好RMQ啊

设A[i]是要求区间最值的数列,F[i, j]表示从第i个数起连续2^j个数中的最大值。(DP的状态)

例如:

A数列为:3 2 4 5 6 8 1 2 9 7

F[1,0]表示第1个数起,长度为2^0=1的最大值,其实就是3这个数。同理 F[1,1] = max(3,2) = 3, F[1,2]=max(3,2,4,5) = 5,F[1,3] = max(3,2,4,5,6,8,1,2) = 8;

并且我们可以容易的看出F[i,0]就等于A[i]。(DP的初始值)

这样,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])。

其实还是二分的思想

(二)然后是查询。

假如我们需要查询的区间为(i,j),那么我们需要找到覆盖这个闭区间(左边界取i,右边界取j)的最小幂(可以重复,比如查询5,6,7,8,9,我们可以查询5678和6789)。

因为这个区间的长度为j - i + 1, 2^k=j-i+1 , 所以我们可以取k=log2( j - i + 1),则有:RMQ(A, i, j)=max{F[i , k], F[ j - 2 ^ k + 1, k]}。

举例说明,要求区间[2,8]的最大值,k = log2(8 - 2 + 1)= 2,即求max(F[2, 2],F[8 - 2 ^ 2 + 1, 2]) = max(F[2, 2],F[5, 2]);

#include <iostream>#include<cstdio>#include<cmath>using namespace std;const int maxn=50005;int mmax[maxn][20],mmin[maxn][20];void RMQ(int n){    for(int j=1;j<20;j++)    {        for(int i=1;i+(1<<(j-1))<=n;i++)        {            mmax[i][j]=max(mmax[i][j-1],mmax[i+(1<<(j-1))][j-1]);            mmin[i][j]=min(mmin[i][j-1],mmin[i+(1<<(j-1))][j-1]);        }    }}int main(){    /*int ans=1;                数据范围是50000,算出2的多少次方可以全覆盖    for(int i=1;i<=20;i++)    {        ans*=2;    }    cout<<ans<<endl;*/    int n,q;    while(scanf("%d%d",&n,&q)!=-1)    {        for(int i=1;i<=n;i++)        {            scanf("%d",&mmax[i][0]);            mmin[i][0]=mmax[i][0];        }        RMQ(n);        int tmp1,tmp2;        while(q--)        {            int l,r;            scanf("%d%d",&l,&r);            int k=(int)(log(r-l+1)/log(2.0));            tmp1=max(mmax[l][k],mmax[r-(1<<k)+1][k]);            tmp2=min(mmin[l][k],mmin[r-(1<<k)+1][k]);            printf("%d\n",tmp1-tmp2);        }    }    return 0;}
原创粉丝点击