poj3264

来源:互联网 发布:mysql 创建触发器 编辑:程序博客网 时间:2024/05/01 01:22

Description

For the daily milking, Farmer John's N cows(1 ≤ N ≤ 50,000) always line up in the same order. One dayFarmer John decides to organize a game of Ultimate Frisbee with some of thecows. To keep things simple, he will take a contiguous range of cows from themilking lineup to play the game. However, for all the cows to have fun theyshould 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 todetermine the difference in height between the shortest and the tallest cow inthe group.

Input

Line 1: Two space-separated integers, N and Q
Lines 2..N+1: Line i+1 contains a single integer that is theheight of cow i 
Lines N+2..N+Q+1: Two integers A and B (1≤ A ≤ B ≤ N), representing therange of cows from A to B inclusive.

Output

Lines 1..Q: Each line contains a single integerthat is a response to a reply and indicates the difference in height betweenthe tallest and shortest cow in the range.

 

题目大意为:

       任意输入一组数字(A1,A2, A3 ……Ai), 求任意区间(Ai……Aj)中的最大数和最小数的差(Max(Ai)- Min(Aj))。

这是一个很基础的线段树题目

代码如下:

#include<iostream>
using namespace std ;
const int INF = 99999999 ;
int min = INF ;
int max = -INF ;
struct Node
{
    int L, R ;
    int s_min, s_max ;
};
Node tree[800000] ;
void BuildTree(int root, int L, int R) ;
void Insert(int root, int i, int v) ;
void Query(int root, int s, int e) ;
int Max(int a, int b) ;
int Min(int a, int b) ;
int main()
{
    int a, b, sign ;
       int i;
    scanf("%d %d", &a, &b) ;
    BuildTree(0, 1, a) ;
    for(i = 1; i <= a; i++ )
    {
        scanf("%d", &sign) ;
        Insert(0, i, sign) ;
    }
    for(i = 0; i < b; i++  )
    {
        int s, e;
        scanf("%d %d", &s, &e) ;
        min = INF ;
        max = -INF ;
        Query(0, s, e) ;
        printf("%d\n", max - min) ;
    }
    return 0 ;
}
void BuildTree(int root, int L, int R)
{
    tree[root].L = L ;
    tree[root].R = R ;
    tree[root].s_min = INF ;
    tree[root].s_max = -INF ;
    if(L != R)
    {
        BuildTree(2*root+1, L, (L+R)/2) ;
        BuildTree(2*root+2, (L+R)/2+1, R) ;
    }
}
void Insert(int root, int i, int v)
{
    if(tree[root].L == tree[root].R)
    {
        tree[root].s_min = tree[root].s_max = v ;
        return ;
    }
    tree[root].s_min = Min(tree[root].s_min, v) ;
    tree[root].s_max = Max(tree[root].s_max, v) ;
    if(i <= (tree[root].L+tree[root].R)/2)
    {
        Insert(2*root + 1, i, v) ;
    }
    else
    {
        Insert(2*root + 2, i, v) ;
    }
}
void Query(int root, int s, int e)
{
    if(tree[root].s_min >= min && tree[root].s_max <=max)
        return ;
    if(tree[root].L == s && tree[root].R == e)
    {
        min = Min(min, tree[root].s_min) ;
        max = Max(max, tree[root].s_max) ;
        return ;
    }
    if(e <= (tree[root].L+tree[root].R)/2)
        Query(2*root + 1, s, e) ;
    else if(s > (tree[root].L+tree[root].R)/2)
        Query(2*root + 2, s, e) ;
    else
    {
        Query(2*root+1, s, (tree[root].L+tree[root].R)/2) ;
        Query(2*root+2, (tree[root].L+tree[root].R)/2+1, e);
    }
}
int Max(int a, int b)
{
       if(a >= b)
              return a ;
       else
              return b ;
}
int Min(int a, int b)
{
       if(a <= b)
              return a ;
       else
              return b ;
}

主要代码为以下三个函数:

void BuildTree(int root, int L, int R) ,voidInsert(int root, int i, int v) ,voidQuery(int root, int s, int e) 。 Build()是建立一个线段树, Insert()是把每输入一个数后,就将这个数插入到已经建立好的线段树中,插入的位置以这个数是第几次输入的为索引。Query()就是解决任意区间中最大数和最小数的查询函数了。

解决题目之前,需要思考,树的的每个结点中放些什么,结点中必须要有的有:区间起点L,和区间终点R([L,R])。每个结点表示一个区间, 题目要求是:求出任意区间中最大数和最小数的差,所以,每个结点Node中还需要存max和min,于是Node结点就定义出来了:

struct Node
{
    int L, R ;
    int s_min, s_max ;
};

Build()和Insert()为线段树必须要有的两个模板函数。

Query()用来查询,如何查询? 每个结点代表一个区间,那么我们就判断输入的区间是否和树中某个结点的L和R相等,相等就将结点中的max和min取出来,否就继续啊向下查询。

0 0
原创粉丝点击