线段树+最大最小值查询+敌兵布阵

!!!!超级开心今天是集训以来听得最清楚的一节课了!真的是第一次这么快搞懂真的超开心谢谢斌哥虽然不知道能不能被看到叭2333!
好了言归正传。
线段树是一棵二叉树,最基本的代码模板是,建树函数、查询函数、更新函数。
建树的时候用深搜的方法,先建立完所有的2n,即左节点,然后逐渐补齐右节点。
哎呀不知道怎么讲啦直接贴代码注释叭哈哈哈哈
嗯对了最大最小值查询没有更新点哦敌兵布阵今天可能来不及写了那个有更新的

嘛又没有写完orz

最大最小值查询

发布时间: 2017年8月7日 10:43 时间限制: 1000ms 内存限制: 128M

描述

输入n个数,我们要对这n个数进行q次查询,每次查询从第L个数到第R个数的最大值或者最小值,输出每次查询的结果。

输入
输入包含对组测试数据,每组测试数据第一行为两个正整数n,q表示一共有n个正整数,q次查询。

接来下一行共有n个正整数。

接下来共有q行数据,每行包含三个正整数,分别为L,R,C。其中L表示查询闭区间的左边界,R表示查询闭区间的右边界,C等于0则返回闭区间内的最小值,C等于1时则返回闭区间内的最大值。

(1<=n<=100000,1<=q<=10000,1<=L<=R<=n,0<=C<=1)

输出
对于每次查询,输出查询结果,占一行。

样例输入1 复制 5 2
1 2 3 4 5
2 3 0
2 3 1

样例输出1 2
3

#include"iostream"
#include"string.h"
#include"math.h"
#include"algorithm"
using namespace std;

int a[100005];
struct tree
{
    int left=0;                             //左节点
    int right=0;                            //右节点
    int max=-1000000;                       //初始化最大值
    int min=1000000;                        //初始化最小值
}tree[400020];                              //建立一个结构体


void buildtree(int root, int left, int right)                  //建立一个树
{
    tree[root].left = left;
    tree[root].right = right;
    if (left == right)
    {
        tree[root].max = a[left];
        tree[root].min = a[left];
        return;
    }
    int mid = (left + right) / 2;
    buildtree(root * 2, left, mid);
    buildtree(root * 2 + 1, mid + 1, right);

    tree[root].max = max(tree[root * 2].max, tree[root * 2 + 1].max);
    tree[root].min = min(tree[root * 2].min, tree[root * 2 + 1].min);

    return;
}

int findmax(int root,int left,int right)
{
    if (left == tree[root].left&&right == tree[root].right)
        return tree[root].max;
    int mid = (tree[root].left + tree[root].right) / 2;
    if (right <= mid)
        return findmax(root * 2, left, right);
    else if (left >= mid+1)
        return findmax(root * 2+1 , left, right);
    else
        return max(findmax(root * 2, left, mid), findmax(root * 2 + 1, mid+1, right));
}

int findmin(int root,int left, int right)
{
    if (left == tree[root].left&&right == tree[root].right)
        return tree[root].min;
    int mid = (tree[root].left + tree[root].right) / 2;
    if (right <= mid)
        return findmin(root * 2, left, right);
    else if (left >= mid+1)
        return findmin(root * 2+1 , left, right);
    else
        return min(findmin(root * 2, left, mid), findmin(root * 2 + 1, mid+1, right));

}



int main()
{
    int n, q;
    while(cin >> n >> q)
    {
        memset(a, 0, sizeof(a));
        int l, r, c;
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        buildtree(1, 1, n);
        for (int i = 1; i <= q; i++)
        {
            cin >> l >> r >> c;
            int root = 1;
            if (c == 0)
                cout << findmin(root, l, r) << endl;
            else
                cout << findmax(root, l, r) << endl;
        }
    }

    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值