题目大意:
现只有一个测例,给出一列数(范围为[1, 1000000]),这一列中总共有N个数(1 ≤ N ≤ 50,000),按照编号顺序1 ~ N排列,现在又Q此询问(1 ≤ Q ≤ 200,000),每次询问一段区间编号[A, B](1 ≤ A ≤ B ≤ N),现要求对于每次询问都要给出在数列中编号A到B中最大值与最小值之差。
注释代码:
/*
* Problem ID : POJ 3264 Balanced Lineup
* Author : Lirx.t.Una
* Language : C++
* Run Time : 1672 ms
* Run Memory : 1184 KB
*/
#include <limits.h>
#include <stdio.h>
#define INF INT_MAX
//线段树根结点
#define ROOT 1
//奶牛的最大数量
#define MAXCOWN 50000
#define LFT(T) ( (T) << 1 )
#define RHT(T) ( LFT(T) | 1 )
typedef struct {//线段树结点中只保留两个域
//区间中的最大值以及最小值
//区间域直接由递归第一层传参而得
int min;
int max;
} Node;
Node seg[MAXCOWN << 2];//线段树
//每次查询的最终答案都保存在这两个全局变量中
int g_max, g_min;
int
min( int a, int b ) {
return a < b ? a : b;
}
int
max( int a, int b ) {
return a > b ? a : b;
}
void
build( int tree, int lft, int rht ) {
//初始化
seg[tree].min = INF;
seg[tree].max = -INF;
if ( lft != rht ) {
int mid;
mid = ( lft + rht ) >> 1;
build( LFT(tree), lft, mid );
build( RHT(tree), mid + 1, rht );
}
}
void
insert( int tree, int i, int h, int lft, int rht ) {
//对树tree进行插入操作,插入元素在数列中的编号为i
//插入的数值(即高度)为h
//插入数值的区间为[lft, rht]
//相当于对[i, i]区间进行update操作!!!
if ( lft == rht ) {//命中,必定为叶子结点
seg[tree].min = h;
seg[tree].max = h;
return ;
}
int mid;
//未命中则表示i一定处于区间[lft, rht]中,则必须对[i, i]的父结点进行修改
seg[tree].min = min( seg[tree].min, h );
seg[tree].max = max( seg[tree].max, h );
mid = ( lft + rht ) >> 1;
if ( i <= mid ) insert( LFT(tree), i, h, lft, mid );
else insert( RHT(tree), i, h, mid + 1, rht );
}
void
query( int tree, int ql, int qr, int lft, int rht ) {
//ql为query lft,qr为query rht,表示查询的区间为[ql, qr]
//[lft, rht]为搜索的区间,即线段树结点上的区间
if ( lft == ql && qr == rht ) {//命中
//对最终答案进行一定更新
g_min = min( g_min, seg[tree].min );
g_max = max( g_max, seg[tree].max );
return ;
}
int mid;
//未命中
mid = ( lft + rht ) >> 1;
if ( qr <= mid )
query( LFT(tree), ql, qr, lft, mid );
else if ( ql > mid )
query( RHT(tree), ql, qr, mid + 1, rht );
else {
query( LFT(tree), ql, mid, lft, mid );
query( RHT(tree), mid + 1, qr, mid + 1, rht );
}
}
int
main() {
int n, q;//奶牛数量和查询数量
int h;//临时保存每头奶牛的高度
int i, j;//计数变量
scanf("%d%d", &n, &q);
build( ROOT, 1, n );//建数,初始化
for ( i = 1; i <= n; i++ ) {
scanf("%d", &h);
insert( ROOT, i, h, 1, n );
}
while ( q-- ) {
g_min = INF;
g_max = -INF;
scanf("%d%d", &i, &j);//查询区间
query( ROOT, i, j, 1, n );
printf("%d\n", g_max - g_min);
}
return 0;
}
无注释代码:
#include <limits.h>
#include <stdio.h>
#define INF INT_MAX
#define ROOT 1
#define MAXCOWN 50000
#define LFT(T) ( (T) << 1 )
#define RHT(T) ( LFT(T) | 1 )
typedef struct {
int min;
int max;
} Node;
Node seg[MAXCOWN << 2];
int g_max, g_min;
int
min( int a, int b ) {
return a < b ? a : b;
}
int
max( int a, int b ) {
return a > b ? a : b;
}
void
build( int tree, int lft, int rht ) {
seg[tree].min = INF;
seg[tree].max = -INF;
if ( lft != rht ) {
int mid;
mid = ( lft + rht ) >> 1;
build( LFT(tree), lft, mid );
build( RHT(tree), mid + 1, rht );
}
}
void
insert( int tree, int i, int h, int lft, int rht ) {
if ( lft == rht ) {
seg[tree].min = h;
seg[tree].max = h;
return ;
}
int mid;
seg[tree].min = min( seg[tree].min, h );
seg[tree].max = max( seg[tree].max, h );
mid = ( lft + rht ) >> 1;
if ( i <= mid ) insert( LFT(tree), i, h, lft, mid );
else insert( RHT(tree), i, h, mid + 1, rht );
}
void
query( int tree, int ql, int qr, int lft, int rht ) {
if ( lft == ql && qr == rht ) {
g_min = min( g_min, seg[tree].min );
g_max = max( g_max, seg[tree].max );
return ;
}
int mid;
mid = ( lft + rht ) >> 1;
if ( qr <= mid )
query( LFT(tree), ql, qr, lft, mid );
else if ( ql > mid )
query( RHT(tree), ql, qr, mid + 1, rht );
else {
query( LFT(tree), ql, mid, lft, mid );
query( RHT(tree), mid + 1, qr, mid + 1, rht );
}
}
int
main() {
int n, q;
int h;
int i, j;
scanf("%d%d", &n, &q);
build( ROOT, 1, n );
for ( i = 1; i <= n; i++ ) {
scanf("%d", &h);
insert( ROOT, i, h, 1, n );
}
while ( q-- ) {
g_min = INF;
g_max = -INF;
scanf("%d%d", &i, &j);
query( ROOT, i, j, 1, n );
printf("%d\n", g_max - g_min);
}
return 0;
}
单词解释:
lineup:n, 一组人,阵容
contiguous:adj, 连续的,临近的
frisbee:n, 飞盘游戏,飞盘运动
ultimate:adj, 极限的,终极的
milk:vt, 挤奶
line up:vi, 排成一列,整队