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

题面:

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;
}

posted @ 2018-12-06 11:53  DQY_dqy  阅读(248)  评论(1编辑  收藏  举报