POJ3264 Balanced Lineup【线段树】

Balanced Lineup

Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 63040   Accepted: 29405
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

问题链接POJ3264 Balanced Lineup

问题简述

  给定N个数和Q个询问,计算区间最大值与最小值的差。

问题分析

  这个问题可以线段树来解。

  区间值可以通过前缀和之差来计算,然而如果某些值发生变化,通过前缀和来计算区间值就不适用了。通常线段树是用来计算区间和的,解决动态变化的问题。然而,这个问题要计算的不是区间和,而是区间最大值与最小值的差,可以通过改造的线段树进行计算。

  需要注意的是,对于n个数,构造其线段树时,需要4倍的节点。另外,使用结构数组来存储线段树,比起带指针链接的线段树,计算效率要高一些。

  这里构造的线段树,根节点下标为0。某个节点的下标为i,则其左右子节点的下标分别为i×2+1和i×2+2。

程序说明

  使用线段树后,其他都是套路。

  这里假设整数类型int是32位的。那么最大值就可以使用程序中定义的INF,最小值可以用-INF。

题记:(略)

参考链接:(略)

AC的C++语言程序如下:

/* POJ3264 Balanced Lineup */

#include <iostream>
#include <stdio.h>

using namespace std;

const int INF = 0x3FFFFFFF;
const int N = 5e4;

struct Node {
    int l, r;
    int minv, maxv;
    int mid() {return (l + r) >> 1;}     // (l + r) / 2
} tree[N * 4];

int minv, maxv;

void buildTree(int root, int l, int r)
{
    tree[root].l = l;
    tree[root].r = r;
    tree[root].minv = INF;
    tree[root].maxv = -INF;
    if(l != r) {
        buildTree(2 * root + 1, l, (l + r) >> 1);
        buildTree(2 * root + 2, ((l + r) >> 1) + 1, r);
    }
}

void insert(int root, int i, int v)
{
    if(tree[root].l == tree[root].r)
        tree[root].minv = tree[root].maxv = v;
    else {
        tree[root].minv = min(tree[root].minv, v);
        tree[root].maxv = max(tree[root].maxv, v);
        if(i <= tree[root].mid())
            insert(2 * root + 1, i, v);
        else
            insert(2 * root + 2, i, v);
    }
}

void query(int root, int s, int e)
{
    if(minv <= tree[root].minv && tree[root].maxv <= maxv)
        ;
    else if(tree[root].l == s && tree[root].r == e) {
        minv = min(minv, tree[root].minv);
        maxv = max(maxv, tree[root].maxv);
    } else if(e <= tree[root].mid())
        query(2 * root + 1, s, e);
    else if(s > tree[root].mid())
        query(2 * root + 2, s, e);
    else {
        query(2 * root + 1, s, tree[root].mid());
        query(2 * root + 2, tree[root].mid() + 1, e);
    }
}

int main()
{
    int n, q;
    while(~scanf("%d%d", &n, &q)) {
        buildTree(0, 1, n);
        for(int i = 1; i <= n; i++) {
            int h;
            scanf("%d", &h);
            insert(0, i, h);
        }
        while(q--) {
            int s, e;
            scanf("%d%d", &s, &e);
            minv = INF;
            maxv = -INF;
            query(0, s, e);
            printf("%d\n", maxv - minv);
        }
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/tigerisland45/article/details/81319242