您的位置:首页 > 其它

POJ 3264 Balanced Lineup(线段树、RMQ)

2016-08-16 23:30 585 查看
题目:

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


这个题目可以用线段树来做,也可以用RMQ来做

RMQ代码:

//为什么数组第二个维度开16是错的,17是对的。。。
#include<iostream>
using namespace std;

int maxs[50000][17];
int mins[50000][17];

int main()
{
int n, q, k, low, high, rmax, rmin;
cin >> n >> q;
for (int i = 0; i < n; i++)
{
scanf("%d", &maxs[i][0]);
mins[i][0] = maxs[i][0];
}
for (int j = 1; (1 << j) <= n; j++)
{
for (int i = 0; i < n; i++)
{
maxs[i][j] = maxs[i][j - 1];
mins[i][j] = mins[i][j - 1];
k = i + (1 << (j - 1));
if (k < n && maxs[i][j] < maxs[k][j - 1])maxs[i][j] = maxs[k][j - 1];
if (k < n && mins[i][j] > mins[k][j - 1])mins[i][j] = mins[k][j - 1];
}
}
while (q--)
{
scanf("%d%d", &low, &high);
low--;
high--;
int j = 0;
while ((1 << j) <= high - low)j++;
j--;
rmax = maxs[high + 1 - (1 << j)][j];
if (rmax < maxs[low][j])rmax = maxs[low][j];
rmin = mins[high + 1 - (1 << j)][j];
if (rmin > mins[low][j])rmin = mins[low][j];
printf("%d\n", rmax - rmin);
}
return 0;
}


写RMQ的代码要注意,main函数里面完全没有出现50000,也没有出现17,关于越界的一切计算都必须靠n,和数组开多大无关。当然,数组一定要足够大。

线段树代码:

#include<iostream>
using namespace std;

int num[50001];
int maxx[200001];
int minn[200001];

void build(int key, int low, int high)
{
if (low == high)
{
minn[key] = maxx[key] = num[low];
return;
}
int mid = (low + high) / 2;
build(key * 2, low, mid);
build(key * 2 + 1, mid + 1, high);
maxx[key] = (maxx[key * 2] > maxx[key * 2 + 1]) ? maxx[key * 2] : maxx[key * 2 + 1];
minn[key] = (minn[key * 2] < minn[key * 2 + 1]) ? minn[key * 2] : minn[key * 2 + 1];
}

int querymaxx(int key, int low, int high, int x, int y)
{
if (low == x && high == y)return maxx[key];
int mid = (low + high) / 2;
if (mid < x)return querymaxx(key * 2 + 1, mid + 1, high, x, y);
if (mid >= y)return querymaxx(key * 2, low, mid, x, y);
int a = querymaxx(key * 2, low, mid, x, mid);
int b = querymaxx(key * 2 + 1, mid + 1, high, mid + 1, y);
return  (a>b) ? a : b;
}

int queryminn(int key, int low, int high, int x, int y)
{
if (low == x && high == y)return minn[key];
int mid = (low + high) / 2;
if (mid < x)return queryminn(key * 2 + 1, mid + 1, high, x, y);
if (mid >= y)return queryminn(key * 2, low, mid, x, y);
int a = queryminn(key * 2, low, mid, x, mid);
int b = queryminn(key * 2 + 1, mid + 1, high, mid + 1, y);
return  (a<b) ? a : b;
}

int main()
{
int n, q, low, high;
cin >> n >> q;
for (int i = 1; i <= n; i++)scanf("%d", &num[i]);
build(1, 1, n);
while (q--)
{
scanf("%d%d", &low, &high);
printf("%d\n", querymaxx(1, 1, n, low, high) - queryminn(1, 1, n, low, high));
}
return 0;
}


因为没有更新操作,所以省掉了update函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: