http://poj.org/problem?id=3264
Balanced Lineup
Time Limit: 5000MS |
|
Memory Limit: 65536K |
Total Submissions: 26465 |
|
Accepted: 12418 |
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
Source
USACO 2007 January Silver
解析:纯线段树或树状数组也行
//wronganswer???why
#include
#include
#include
using namespace std;
const int inf=1<<30;
const int N=50000+10;
int num[N],MIN,MAX;
struct Tr
{
int l;
int r;
int minn,maxn;
}tree[4*N];
/*int max(int a,int b)
{
return a>b? a:b;
}
int min(int a,int b)
{
return a
}*/
void bulid(int l,int r,int k)//创建以num[]数组元素序号的线段树,、
//并且在每段中增加一个最小值和最大值,k表示线段树序号
{tree[k].l=l;
tree[k].r=r;
if(l==r)//递归边界
{
tree[k].minn=tree[k].maxn=num[l];
return;
}
int m=(l+r)/2;
//printf("m=%d ",m);
bulid(l,m,2*k);
bulid(m+1,r,2*k+1);
tree[k].minn=min(tree[2*k].minn,tree[2*k+1].minn);
tree[k].maxn=max(tree[2*k].maxn,tree[2*k+1].maxn);
}
void query(int l,int r,int k)//寻找到(l.r)所在区间 段
{
if(l<=tree[k].l&&r>=tree[k].r)//边界表示已找到l,r所在区间段
{
MIN=min(tree[k].minn,MIN);
MAX=max(tree[k].maxn,MAX);
return;
}
int m=(tree[k].l+tree[k].r)/2;
if(l>m)query(l,r,2*k+1);
else if(r<=m)query(l,r,k*2);//分别在左右子树 分布情况
else
{query(l,r,k*2);
query(l,r,2*k+1);
}
}
int main()
{
int i,n,m;
int a,b;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d",&num[i]);
bulid(1,n,1);
// for(i=1;i<=n;i++)
//printf("(%d, %d) (%d, %d)\n",tree[i*2].l,tree[i*2].r,tree[i*2+1].l,tree[i*2+1].r);
for(i=0;i
{
scanf("%d%d",&a,&b);
MIN=inf;
MAX=-inf;
query(a,b,1);
printf("%d\n",MAX-MIN);
}
// system("pause");
return 0;
PS:j今天看了之后终于过了,原因很简单因为我设置的z字母‘l’和数字‘1’在屏幕上显示的是一样的所以怎奈我看啊看啊,还是看不出来,
教训:最好将字符和数字设子成颜色易于分辨的颜色
//Accept
#include
#include
#include
using namespace std;
const int inf=1<<30;
const int N=50010;
struct node
{
int l,r;
int maxn,minn;
}tree[N<<2];
int num[N],MAX,MIN;
void build(int l,int r,int k)
{
tree[k].l=l;
tree[k].r=r;
if(l==r)
{
tree[k].maxn=tree[k].minn=num[l];
return;
}
int m=(l+r)/2;
//printf("mid=%d",mid);
build(l,m,k*2);
build(m+1,r,k*2+1);
tree[k].maxn=max(tree[k*2].maxn,tree[k*2+1].maxn);
tree[k].minn=min(tree[k*2].minn,tree[k*2+1].minn);
}
void query(int l,int r,int k)
{
if(l<=tree[k].l&&r>=tree[k].r)
{
MAX=max(tree[k].maxn,MAX);
MIN=min(tree[k].minn,MIN);
return;
}
int m=(tree[k].l+tree[k].r)/2;
if(m=r)query(l,r,k*2);
else {
query(l,r,k*2);
query(l,r,k*2+1);
}
}
int main()
{
int n,m,b,a,i;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d",&num[i]);
build(1,n,1);
// for(int i=1;i<=n;i++)
//printf("(%d, %d) (%d, %d)\n",tree[i*2].l,tree[i*2].r,tree[i*2+1].l,tree[i*2+1].r);
for( i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
MAX=-inf;
MIN=inf;
query(a,b,1);
printf("%d\n",MAX-MIN);
}
//system("pause");
return 0;
}
//
/李ACCEpT
*Accepted
*2388 KB
*1766 ms
*C++
*1690 B
*/
#include
#include
#include
#include
using namespace std;
#define N 50001
int v[N],Max,Min;
struct node{
int left,right;
int max,min;
int mid()
{ return (left+right)/2;}
}T[N*3];
void build(int root,int l,int r) //建树
{
T[root].left = l;
T[root].right = r;
//printf("%d %d",T[root].left,T[root].right); //建树的时候可以“单步调试”,看它是怎么建的
if(l == r)//如果没有孩子了,说明孩子树已经建完了
{
T[root].max = T[root].min = v[l];
return ;
}
else
{
int mid = T[root].mid();
build(root<<1, l,mid);//建树的顺序是从左到右,root<<1相当于root*2
build(root<<1|1, mid+1,r);//root<<1|1相当于root*2+1
T[root].max = max(T[root*2].max, T[root*2+1].max);
T[root].min = min(T[root*2].min, T[root*2+1].min);
}
}
void query(int root,int l,int r)//查找线段
{
// printf("%d %d",T[root].left,T[root].right); //查找的时候可以“单步调试”,看它是怎么查找的
if(T[root].left==l && T[root].right==r)
{
Max=max(T[root].max, Max);
Min=min(T[root].min, Min);
return ;
}
else
{
int mid=T[root].mid();
if(r <= mid)//在左孩子找
{
query(root<<1, l, r);
}
else if(l > mid)//在右孩子找
{
query(root<<1|1, l, r);
}
else //拆两半
{
query(root<<1, l, mid);
query(root<<1|1, mid+1, r);
}
}
}
int main()
{
int i,j,n,m;
scanf("%d%d", &n, &m);
for(i = 1; i <= n; i++)
scanf("%d",&v[i]);
build(1, 1, n);
for(i = 1;i <= m; i++)
{
int st, en;
scanf("%d%d", &st, &en);
Max=-1000111222;
Min=1000111222;
query(1,st,en);
printf("%d\n",Max-Min);
}
return 0;
}