[POJ]3264 Balanced Lineup

 转载请注明出处:http://www.cnblogs.com/StartoverX/p/4618041.html 

题目:

 

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

 

 

 

题目分析:

  输入为N和Q,N为数据的数目1<=N<=50000,每个数据的大小为H(1<=H<=1000000)。Q为询问的次数,1<=Q<=200000,要求给出每次询问范围内的最大值和最小值之差。

  要求数组中的最大值和最小值,首先想到的就是遍历数组,然而,本题中,如果对每次询问都遍历一遍给定范围,则时间复杂度为O(N*Q),太大。进一步分析发现,本题中的数组大小是给定的,对同一个数组范围进行大量的查询操作,理所当然想到用线段树,这样可以将每一次查询操作的复杂度降为O(lgN),总复杂度为O(lgN*Q)。

解决方案:

#include <stdio.h>
int cow[50010]; typedef struct Tree { int min;//用线段树保存最大最小值信息。
    int max; int right; int left; Tree* right_node; Tree* left_node; }Tree; //在递归建树的同时后序遍历得到每个线段树node范围内的最大最小值。
Tree* build(int a,int b) { Tree* tree = new Tree; tree->right = b; tree->left = a; if(b == a) { tree->right_node = NULL; tree->left_node = NULL; tree->min = cow[tree->left]; tree->max = cow[tree->right]; } else if(b > a) { int mid = (a+b)/2; tree->right_node = build(mid+1,b); tree->left_node = build(a,mid); tree->min =(tree->right_node->min < tree->left_node->min) ? tree->right_node->min : tree->left_node->min; tree->max =(tree->right_node->max > tree->left_node->max) ? tree->right_node->max : tree->left_node->max; } return tree; } //查询操作,若查询范围和node范围一致,直接返回最大最小值,否则继续递归查询。
void query(Tree* tree,int a,int b,int& min,int& max) { if(a == tree->left && b == tree->right) { min = tree->min; max = tree->max; return; } int mid = (tree->right + tree->left)/2; if(a > mid) { query(tree->right_node,a,b,min,max); } else if(b <= mid) { query(tree->left_node,a,b,min,max); } else { int min_temp1,max_temp1; query(tree->left_node,a,mid,min_temp1,max_temp1); int min_temp2,max_temp2; query(tree->right_node,mid+1,b,min_temp2,max_temp2); min = min_temp1 < min_temp2 ? min_temp1 : min_temp2; max = max_temp1 > max_temp2 ? max_temp1 : max_temp2; } } int main() { int n,q; scanf("%d %d",&n,&q); for(int i=1;i<=n;i++) { scanf("%d",&cow[i]); } Tree* tree = build(1,n); for(int i=0;i<q;i++) { int a,b; scanf("%d %d",&a,&b); int min_in,max_in; query(tree,a,b,min_in,max_in); printf("%d\n",max_in-min_in); } return 0; }

 

一个教训:处理输入输出用c的方式stdio,不要用c++ iostream,太慢了,这道题在这里被卡了时间。

 

你可能感兴趣的:(poj)