最敏捷的机器人(线段树维护区间最值)

本文介绍了一种利用线段树数据结构解决区间最大值和最小值查询问题的方法。通过构建线段树,可以高效地进行区间最值查询,适用于需要频繁查询区间最值的场景。文章提供了完整的代码实现,并解释了查询过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题面:

Wind设计了很多机器人。但是它们都认为自己是最强的,于是,一场比赛开始了……机器人们都想知道谁是最敏捷的,于是它们进行了如下一个比赛。首先,他们面前会有一排共n个数,它们比赛看谁能最先把每连续k个数中最大和最小值写下来,当然,这些机器人运算速度都很,它们比赛的是谁写得快。但是Wind也想知道答案,你能帮助他吗?

Input:

每组测试数据
第1行为n,k(1<=k<=n<=100000)
第2行共n个数,为数字序列,所有数字均在int范围内。

Output:

共n-k+1行
第i行为第i~i+k-1这k个数中的最大和最小值

Sample Input:

5 3
1 2 3 4 5

Sample Output:

3 1
4 2
5 3

Solution:

线段树维护区间最大值和区间最小值,再暴力查询即可
要注意的是给出的数字可能为负数(在int范围内)

Code:
#include<bits/stdc++.h>
using namespace std;
int n,m,a[1000001];
struct sgt{
    struct node{int minn,maxn;}tree[500001];
    void build(int k,int l,int r){
        if(l==r){
            tree[k].minn=tree[k].maxn=a[l];
            return ;
        }
        int mid=(l+r)>>1;
        build(k<<1,l,mid);build(k<<1|1,mid+1,r);
        tree[k].minn=min(tree[k<<1].minn,tree[k<<1|1].minn);
        tree[k].maxn=max(tree[k<<1].maxn,tree[k<<1|1].maxn);
    }
    int query_min(int L,int R,int l,int r,int k){
        if(l>R||r<L)return 2147483647;
        if(l>=L&&r<=R)return tree[k].minn;
        int re=2147483647;
        int mid=(l+r)>>1;
        re=min(query_min(L,R,l,mid,k<<1),query_min(L,R,mid+1,r,k<<1|1));
        return re;
    }
    int query_max(int L,int R,int l,int r,int k){
        if(l>R||r<L)return -2147483647;
        if(l>=L&&r<=R)return tree[k].maxn;
        int re=-2147483647;
        int mid=(l+r)>>1;
        re=max(query_max(L,R,l,mid,k<<1),query_max(L,R,mid+1,r,k<<1|1));
        return re;
    }
}T;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int main(){
    n=read();m=read();
    for(int i=1;i<=n;i++)a[i]=read();
    T.build(1,1,n);
    for(int i=1;i<=n-m+1;i++)
        printf("%d %d\n",T.query_max(i,i+m-1,1,n,1),T.query_min(i,i+m-1,1,n,1));
    return 0;
}

转载于:https://www.cnblogs.com/NLDQY/p/10075925.html

### C++ 线段树实现区间查询 #### 构建线段树 为了构建一棵能够维护区间线段树,需要初始化一个大小为 `4 * n` 的数组作为节点存储空间。这里假设输入的是长度为 `n` 的数组 `arr[]`。 ```cpp const int MAXN = 1e5 + 5; int segTree[MAXN << 2]; // 定义线段树结点数量, 使用位运算表示乘法 void build(int node, int start, int end) { if (start == end) { // 叶子节点情况 segTree[node] = arr[start]; return; } int mid = (start + end) >> 1; // 计算中间位置 build(node<<1, start, mid); // 左孩子递归建立 build((node<<1)|1, mid+1, end); // 右孩子递归建立 segTree[node] = max(segTree[node<<1], segTree[(node<<1)|1]); // 合并左右孩子的 } ``` 此部分描述了如何创建一颗线段树来保存给定序列的信息[^1]。 #### 区间查询 当完成线段树的构造之后,就可以利用它来进行高效的区间查询操作: ```cpp int queryMax(int node, int start, int end, int L, int R) { if (R < start || end < L) return INT_MIN; // 当前范围完全不在询问范围内 if (L <= start && end <= R) return segTree[node]; // 范围被完全覆盖的情况 int mid = (start + end) >> 1; int q1 = queryMax(node*2, start, mid, L, R); int q2 = queryMax(node*2+1, mid+1, end, L, R); return max(q1, q2); // 返回两个子区间的较大者 } ``` 上述函数实现了在线段树上执行区间 `[L,R]` 内的查找功能[^2]。 #### 单点更新 对于单个元素的变化,则可以通过下面的方式快速调整对应的线段树状态: ```cpp void updateNode(int node, int start, int end, int idx, int val){ if(start==end){ arr[idx]=val; segTree[node]=val; return ; } int mid=(start+end)>>1; if(idx<=mid) updateNode(2*node,start,mid,idx,val); else updateNode(2*node+1,mid+1,end,idx,val); segTree[node]=max(segTree[2*node],segTree[2*node+1]); } ``` 这段代码展示了怎样在改变原数组某一位数的同时保持线段树的一致性和有效性[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值