POJ3264——Balanced Lineup(线段树)

简介:

本文出自:http://blog.csdn.net/svitter


题意:在1~200,000个数中。取一段区间。然后在区间中找出最大的数和最小的数字。求这两个数字的差。

分析:按区间取值,非常明显使用的线段树。

区间大小取200000 * 4 = 8 * 10 ^5;

          进行查询的时候。注意直接推断l, r 与mid的关系就可以。一開始写的时候直接与tree[root].L推断,多余了,

          逻辑不对。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace std;
const int INF = 0xffffff;
int maxV, minV;


struct Node
{
    int L, R;
    int Mid(){ return (L+R)/2;}
    int maxV, minV;     //最大数和最小数
    //Node *lchild, *rchild;    使用一位数组就能够不使用,能够看做全然二叉树(可能存在空间浪费)
};

Node tree[800010];           //四倍叶子节点

void Insert(int root, int n, int val)
{
    //推断叶子节点
    if(tree[root].L == tree[root].R)
    {
        tree[root].maxV = tree[root].minV = val;
        return;
    }

    //递归更新
    tree[root].minV = min(tree[root].minV, val);
    tree[root].maxV = max(tree[root].maxV, val);


    //当前为区间节点,寻找叶子节点
    if(n < tree[root].Mid())
    {
        Insert(root*2+1, n, val);
    }
    else
    {
        Insert(root*2+2, n, val);
    }
}


void BuildTree(int root, int l, int r)
{
    //建立当前节点
    tree[root].L = l;
    tree[root].R = r;
    tree[root].maxV = -INF;
    tree[root].minV = INF;
    //递归调用建立子树
    if(l != r)
    {
        BuildTree(root*2+1, l, (l+r)/2);
        BuildTree(root*2+2, (l+r)/2+1, r);
    }

}

void Query(int root, int l, int r)
{
    //递归终止条件
    if(l < tree[root].L || r > tree[root].R)
        return;

    //推断条件:全然符合区间
    if(l == tree[root].L && r == tree[root].R)
    {
        maxV = max(maxV, tree[root].maxV);
        minV = min(minV, tree[root].minV);
        return;
    }

    if(r <= tree[root].Mid())
        Query(root*2+1, l, r);
    else if(l > tree[root].Mid())
        Query(root*2+2, l, r);
    else
    {
        Query(root*2+1, l, tree[root].Mid());
        Query(root*2+2, tree[root].Mid()+1, r);
    }
}


int main()
{
    int N, Q;
    int val;
    int a, b;         //查找区间[a,b]
    //while(scanf("%d%d", &N, &Q))
    scanf("%d%d", &N, &Q);
    {

        BuildTree(0, 1, N);
        for(int i = 0; i < N; i ++)
        {
            scanf("%d", &val);
            Insert(0, i, val);
        }
        //用于測试线段树生成情况
//        for(int i = 0; i < 7; i++)
//        {
//            printf("No:%d,\nL: %d,\nR: %d,\nMAX: %d,\nMIN: %d,\n\n", i, tree[i].L, tree[i].R, tree[i].maxV, tree[i].minV);
//        }
        while(Q--)
        {
            maxV = -INF, minV = INF;
            scanf("%d%d", &a, &b);
            Query(0, a, b);
//            printf("max: %d\nmin: %d\n", maxV, minV);
            printf("%d\n", maxV - minV);
        }
    }

    return 0;
}






本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5179569.html,如需转载请自行联系原作者
相关文章
|
8月前
|
Java
POJ- 2367- Genealogical tree【拓扑排序】
POJ- 2367- Genealogical tree【拓扑排序】
33 0
Optimization for UltraNet二分最小生成树
二分边,要把边最小值尽可能最大化,可以对这个值进行二分判断是否可以,在判断的过程中,如果是要连接的次数等于n-1,n为点的数量,点之间如果要构成生成树最少连接的数量为n-1,所以说判断的时候可以通过连接的次数来判断是否可以构成生成树 将最小生成树的那条边进行最小值的最大化之后,就可以再往后遍历的过程中,把要用到的n-1条边进行记录下来,然后进行下一步操作->计算边权 将要用到的边记录下来之后,按照边权的大小对他进行从大到小进行排序,用并查集来维护两个联通块的大小,这个联通块对答案的贡献就是两个联通块的大小size_a * size_b * w
149 0
Optimization for UltraNet二分最小生成树
|
Go
[Nowcoder / POJ2728] 最优比率生成树 | 二分 + prim
有n个点,其中,每个点给出位置坐标( x , y ) 以及高度z ,两点之间的距离为两点之间的欧几里得距离 两点之间建立一条路的代价为两点之间的高度差,问将n 个点联通的情况下,求出最大的cost/dis
137 0
|
人工智能 数据建模 BI
POJ 3662 Telephone Lines【Dijkstra最短路+二分求解】
Telephone Lines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7214   Accepted: 2638 Description Farmer John wants to set up a telephone line at his farm.
1154 0