poj3264 balanced lineup

Balanced Lineup
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 55020 Accepted: 25769
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

裸的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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章