您的位置:首页 > 理论基础 > 数据结构算法

Balanced Lineup(POJ 3264)(数据结构之线段树)

2016-08-04 19:58 330 查看
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、节点数组里面元素个数是叶子节点个数的4倍即可。

2、线段树问题主要是想好每个节点里面存储什么东西,每个节点的值如何更新,以及查询的时候如何查询。

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <queue>

using namespace std;

struct CNode
{
int l, r;
int minh, maxh;
int Mid()
{
return (l + r) / 2;
}
};

const int maxn = 800010;
const int INF = 1 << 30;
CNode tree[maxn];
int minh, maxh;

void BuildTree(int root, int l, int r)
{
tree[root].l = l;
tree[r
4000
oot].r = r;
tree[root].maxh = -INF;
tree[root].minh = INF;
if (l != r) {
BuildTree (2 * root + 1, l, (l + r) / 2);
BuildTree (2 * root + 2, (l + r) / 2 + 1, r);
}
}

void Insert(int root, int i, int v)
{
if (tree[root].l == tree[root].r) {
tree[root].minh = tree[root].maxh = v;
return;
}
tree[root].minh = min (tree[root].minh, v);
tree[root].maxh = max (tree[root].maxh, 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 (tree[root].minh >= minh && tree[root].maxh <= maxh) return;//这样的话后面的节点就更不用更新了
if (tree[root].l == s && tree[root].r == e) {//到达区间分解终止区
minh = min (minh, tree[root].minh);
maxh = max (maxh, tree[root].maxh);
return;
}
if (e <= tree[root].Mid()) {//继续向下分解,直到分解到终止节点
Query (root * 2 + 1, s, e);
} else if (s > tree[root].Mid()) {
Query (root * 2 + 2, s, e);
} else {
Query (root * 2 + 1, s, tree[root].Mid());
Query (root * 2 + 2, tree[root].Mid() + 1, e);
}
}

int main()
{
#ifndef ONLINE_JUDGE
freopen ("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
int n, q;
scanf ("%d%d", &n, &q);
BuildTree (0, 1, n);
for (int i = 1; i <= n; i++) {//i是从1开始,因为0是无意义的叶子节点,叶子节点从1开始。
int h;
scanf ("%d", &h);
Insert (0, i, h);
}
while (q--) {
int l, r;
scanf ("%d%d", &l, &r);//要用scanf,printf输入输出
minh = INF;
maxh = -INF;
Query (0, l, r);
int answer = maxh - minh;
printf ("%d\n", answer);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: