• 九度 1544 数字序列区间最小值(朴素线段树)


    题目

    给定一个数字序列,查询任意给定区间内数字的最小值。

    思路

    1. 第一反应, 这是在考察 线段树, 链接里的 blog 讲的很不错, 清晰易懂

    2. 这道题不需要考虑插入或者删除线段, 只需要 build 和 统计

    3. 建树的话, 先考虑 node 节点的设计, 题目要求的是区间最小值, 所以自然需要一个域保留当前 node 节点表示区间的最小值.

    class Node {
    public:
        int left, right;
        Node *lchild, *rchild;
        int minVal;
    };

    4. 然后进行递归建树. 区间 [a,b]的最小值 是由 [a,mid] 和 [mid+1, b] 确定的, 典型的后序遍历模式

    Node* buildTree(int a, int b) {
        if(a == b) {
            Node *newNode = new Node();
            newNode->minVal = arr[a-1];
            newNode->left = a;
            newNode->right = b;
            newNode->lchild = NULL;
            newNode->rchild = NULL;
            return newNode;
        }
    
        int mid = (a+b) >> 1;
    
        Node* lNode = buildTree(a, mid);
        Node* rNode = buildTree(mid+1, b);
    
        Node* newNode = new Node();
        newNode->left = a;
        newNode->right = b;
        newNode->lchild = lNode;
        newNode->rchild = rNode;
        newNode->minVal = min(lNode->minVal, rNode->minVal);
        return newNode;
    }

    OK, 树建好了, 现在, 我们拥有这个样子的树了

    5. 最后进行统计

    统计是一个 topDown 的搜索过程, log(n) 时间复杂度

    递归的退出条件是 a = left, b = right

    int search(Node* root, int a, int b) {
        if(root->left == a && root->right == b) {
            return root->minVal;
        }else{
            int mid = (root->left+root->right)>>1;
            if(b <= mid)
                return search(root->lchild, a,b);
            else if(a > mid)
                return search(root->rchild, a, b);
            else {
                int lmin = search(root->lchild, a, mid);
                int rmin = search(root->rchild, mid+1, b);
                return min(lmin, rmin);
            }
        }
    }

    代码 

    #include <iostream>
    #include <stdio.h>
    using namespace std;
    
    const int INFS = 0X3F3F3F3F;
    
    class Node {
    public:
        int left, right;
        Node *lchild, *rchild;
        int minVal;
    };
    
    int arr[200000];
    
    Node* buildTree(int a, int b) {
        if(a == b) {
            Node *newNode = new Node();
            newNode->minVal = arr[a-1];
            newNode->left = a;
            newNode->right = b;
            newNode->lchild = NULL;
            newNode->rchild = NULL;
            return newNode;
        }
    
        int mid = (a+b) >> 1;
    
        Node* lNode = buildTree(a, mid);
        Node* rNode = buildTree(mid+1, b);
    
        Node* newNode = new Node();
        newNode->left = a;
        newNode->right = b;
        newNode->lchild = lNode;
        newNode->rchild = rNode;
        newNode->minVal = min(lNode->minVal, rNode->minVal);
        return newNode;
    }
    
    int search(Node* root, int a, int b) {
        if(root->left == a && root->right == b) {
            return root->minVal;
        }else{
            int mid = (root->left+root->right)>>1;
            if(b <= mid)
                return search(root->lchild, a,b);
            else if(a > mid)
                return search(root->rchild, a, b);
            else {
                int lmin = search(root->lchild, a, mid);
                int rmin = search(root->rchild, mid+1, b);
                return min(lmin, rmin);
            }
        }
    }
    
    int main() {
        freopen("testcase.txt", "r", stdin);
        int len;
        while(scanf("%d", &len) != EOF) {
            for(int i = 0; i < len; i ++)
                scanf("%d", &arr[i]);
            Node *root = buildTree(1, len);
            int queries;
            scanf("%d", &queries);
            for(int i = 0; i < queries; i ++) {
                int a, b;
                scanf("%d%d", &a, &b);
                int res = search(root, a, b);
                printf("%d
    ",res);
            }
        }
        return 0;
    }
  • 相关阅读:
    2019 西安邀请赛 D
    time 库
    字符串处理+格式化输出
    数据类型
    turtle1
    格式问题
    字符串1
    基础操作
    链表去重
    PAT 1093
  • 原文地址:https://www.cnblogs.com/xinsheng/p/3575682.html
Copyright © 2020-2023  润新知