【POJ 3264】Balanced Lineup(RMQ算法||线段树)

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

题意:

一句话概括->求出给定区间内最大值与最小值的差值

思路:

此题可用两种方法写。1.线段树;2.新操作->RMQ算法
什么是RMQ?

Range Minimum/Maximum Query,对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j之间的最小/大值。

可以看出这道题就是一道RMQ算法的裸题。
第一次见到RMQ算法,其实它(的预处理)就是个DP的思想,关键在于状态转移方程的理解。上那篇文章讲的很好可以看看。

代码:

RMQ算法版本
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int maxsum[200001][20],minsum[200001][20];
int n,q;

void Init()
{
    int i,j,lg=floor(log10(double(n))/log10(double(2)));
    for(j=1;j<=lg;j++)
        for(i=1;i<=n;i++)
            if(i+(1<<j)-1<=n)
            {
                maxsum[i][j]=max(maxsum[i][j-1],maxsum[i+(1<<(j-1))][j-1]);
                minsum[i][j]=min(minsum[i][j-1],minsum[i+(1<<(j-1))][j-1]);
            }
}


int main()
{
    int k,a,b,lg;  
    scanf("%d %d", &n, &q);  
    for (int i = 1; i <= n; ++i){  
        scanf("%d", &k);  
        maxsum[i][0] = minsum[i][0] = k;  
    }  
    Init();  
    while(q--){  
        scanf("%d%d", &a, &b);  
        if (a > b) swap(a, b);  
        lg = floor(log10(double(b-a+1))/log10(double(2)));  
        //max(fmax[a][lg], fmax[b-(1<<lg)+1][lg]),两个区间中间有重叠,因此两者中较大的就是该区间的最大值  
        printf("%d\n", max(maxsum[a][lg], maxsum[b-(1<<lg)+1][lg])-min(minsum[a][lg], minsum[b-(1<<lg)+1][lg]));  
    }  
    return 0;   
} 
线段树版本
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAX 200005
#define INF 0xffffff
using namespace std;
struct Tree{
    int left;
    int right;
    int min;
    int max;
}tree[MAX<<2];//一般都是4倍
int maxv,minv;

void Build(int l,int r,int i)
{
    tree[i].left=l;
    tree[i].right=r;
    tree[i].max=-INF;
    tree[i].min=INF;
    if(l==r) return ;
    int mid=(l+r)/2;
    {
        Build(l,mid,i*2+1);
        Build(mid+1,r,i*2+2);
    }
}

void Insert(int i,int x,int val)
{
    if(tree[i].left==tree[i].right)
    {
        tree[i].max=tree[i].min=val;
        return ;
    }
        //递归更新最大最小值
    tree[i].max=max(tree[i].max,val);
    tree[i].min=min(tree[i].min,val);

    int mid=(tree[i].left+tree[i].right)/2;
    if(x<mid) Insert(i*2+1,x,val);
    else Insert(i*2+2,x,val);
}

void Query(int l,int r,int i)
{
    if(l<tree[i].left||r>tree[i].right) return ;

    if(l==tree[i].left&&r==tree[i].right)
    {
        maxv=max(tree[i].max,maxv);
        minv=min(tree[i].min,minv);
        return ;
    }

    int mid=(tree[i].left+tree[i].right)/2;
    if(l>mid) Query(l,r,i*2+2);
    else if(r<=mid) Query(l,r,i*2+1);
    else {
        Query(l,mid,i*2+1);
        Query(mid+1,r,i*2+2);
    }

}


int main()
{
    int n,q,val;
    scanf("%d %d",&n,&q);
    Build(1,n,0); //这里用下标从0开始,下面也是(从1开始不知道为何WA了)
    for(int i=0;i<n;i++)
    {
        scanf("%d",&val);
        Insert(0,i,val);
    }
    while(q--)
    {
        int a,b;
        maxv=-INF,minv=INF;//每次都初始化一下maxv,minv
        scanf("%d %d",&a,&b);
        Query(a,b,0);
        printf("%d\n",maxv-minv);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/chen_yuazzy/article/details/77451064