POJ 3264:Balanced Lineup(线段树应用:区间最大值与最小值之差)
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,后跟着q次查询;求得给定区间最大值与最小值之差,暴力绝对不行,线段树简单应用
ps:感觉第二个代码容易懂
代码一如下:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=0xffffff0;
const int maxN=200010;
int minV=INF;
int maxV=-INF; //表示某一区间内最大值、最小值
/**结点结构*/
struct Node
{
int L,R;
int minV,maxV;
int Mid;
/**如果防止内存超限的话可以
int Mid()
{
return (L+R)/2;
}*/
};
/**用数组代替指针存放树结构(只需保证数组大小为结点数4倍即可)*/
Node tree[4*maxN];
/**建立线段树*/
void build_Tree(int root,int L,int R)
{
tree[root].L=L;
tree[root].R=R;
/*如果用第二种方法的话,这条语句就该去掉*/
tree[root].Mid=(tree[root].L+tree[root].R)/2;
tree[root].minV=INF;
tree[root].maxV=-INF;
if(L!=R)
{
build_Tree(2*root,L,(L+R)/2);
build_Tree(2*root+1,(L+R)/2+1,R);
}
}
/**插入数据(将第i个数,其值为v,插入线段树)*/
void Insert(int root,int i,int v)
{
if(tree[root].L==tree[root].R)
{
tree[root].minV=tree[root].maxV=v;
return;
}
tree[root].minV=min(tree[root].minV,v);
tree[root].maxV=max(tree[root].maxV,v);
if(i<=tree[root].Mid)
Insert(2*root,i,v);
else
Insert(2*root+1,i,v);
}
/**查询(查询区间[s,e]中的最小值和最大值,如果更优就记在全局变量minV,maxV里*/
void Query(int root,int s,int e)
{
if(tree[root].minV>=minV&&tree[root].maxV<=maxV)
return ;
if(tree[root].L==s&&tree[root].R==e)
{
minV=min(minV,tree[root].minV);
maxV=max(maxV,tree[root].maxV);
return;
}
/**区间过大*/
if(e<=tree[root].Mid)
Query(2*root,s,e);
else if(s>tree[root].Mid)
Query(2*root+1,s,e);
/**左右子树*/
else
{
Query(2*root,s,tree[root].Mid);
Query(2*root+1,tree[root].Mid+1,e);
}
}
int main()
{
int n,q;
int num;
scanf("%d%d",&n,&q);
build_Tree(1,1,n);
for(int i=1;i<=n;i++)
{
scanf("%d",&num);
Insert(1,i,num);
}
for(int i=1;i<=q;i++)
{
int s,e; //待查询区间起终点
scanf("%d%d",&s,&e);
minV=INF;
maxV=-INF;
Query(1,s,e);
printf("%d\n",maxV-minV);
}
return 0;
}
另附第二种代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=0xffffff0; //确定一个最大值
const int maxn=50010; //n的最大值
/**结点结构*/
struct Node
{
int L,R;
int minV,maxV;
};
Node tree[4*maxn]; //用数组表示线段树
int a[maxn]; //存放结点数值
int maxV=-INF;
int minV=INF; //存放最大值与最小值
/**建立线段树,并赋初值*/
void build_Tree(int root,int L,int R)
{
tree[root].L=L;
tree[root].R=R;
/**到叶子结点时附值*/
if(L==R)
{
tree[root].maxV=tree[root].minV=a[L];
return ;
}
int mid=(tree[root].L+tree[root].R)/2;
build_Tree(2*root,L,mid);
build_Tree(2*root+1,mid+1,R);
tree[root].minV=min(tree[2*root].minV,tree[2*root+1].minV);
tree[root].maxV=max(tree[2*root].maxV,tree[2*root+1].maxV); //当不是叶子结点时,存放左右孩子的最大值与最小值
}
/**查询区间[s,e]中的最大值与最小值*/
void Query(int root,int s,int e)
{
if(minV<=tree[root].minV&&maxV>=tree[root].maxV)
return;
/**当刚好区间相等时*/
if(tree[root].L==s&&tree[root].R==e)
{
minV=min(minV,tree[root].minV);
maxV=max(maxV,tree[root].maxV);
return ;
}
int mid=(tree[root].L+tree[root].R)/2;
/**区间过大时*/
if(e<=mid)
Query(2*root,s,e);
else if(s>mid)
Query(2*root+1,s,e);
/**左右孩子*/
else
{
Query(2*root,s,mid);
Query(2*root+1,mid+1,e);
}
}
int main()
{
int n,q;
int num;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
build_Tree(1,1,n);
int s,e;
for(int i=1;i<=q;i++)
{
minV=INF;
maxV=-INF;
scanf("%d%d",&s,&e);
Query(1,s,e);
printf("%d\n",maxV-minV);
}
return 0;
}