poj2823------线段树-------求区间最大最小值(RMQ)

如 POJ 3264。

inf 要定义足够大。

注意负数的情况。

判断时注意临界值。


树状数组线段树建树以及节点意义如POJ 3264。


据discuss里好像可以用单调队列。


#include<stdio.h>

#define maxn 1000010
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
int inf = 2100000010;
int n, k;
int c_min, c_max;

struct node{
    int minv, maxv;
    int lc, rc;
}sum[maxn<<2];
int min_ans[maxn];
int max_ans[maxn];
int num[maxn];

int max(int a, int b){
    return a>b?a:b;
}

int min(int a, int b){
    return a<b?a:b;
}

void PushUp(int rt){
    sum[rt].minv = min(sum[rt<<1].minv, sum[rt<<1|1].minv);
    sum[rt].maxv = max(sum[rt<<1].maxv, sum[rt<<1|1].maxv);
}

void build(int l, int r, int rt){
    sum[rt].lc = l;
    sum[rt].rc = r;
    if(l == r){
        scanf("%d", &sum[rt].minv);
        sum[rt].maxv = sum[rt].minv;
        return ;
    }
    int m = (l+r)>>1;
    build(lson);
    build(rson);
    PushUp(rt);
}

void Query(int L, int R, int l, int r, int rt){
    if(L == sum[rt].lc && R == sum[rt].rc){
        if(sum[rt].minv < c_min) c_min = sum[rt].minv;
        if(sum[rt].maxv > c_max) c_max = sum[rt].maxv;
        return ;
    }
    int m = (l+r)>>1;
    if(L <= m){
        if(R > m) Query(L, m, lson);
        else Query(L, R, lson);
    }
    if(R > m){
        if(L < m+1) Query(m+1, R, rson);
        else Query(L, R, rson);
    }
}

int main(){
    freopen("in.txt", "r", stdin);
    int cnt;
    while(scanf("%d %d", &n, &k) != EOF){
        cnt = 0;
        build(1, n, 1);
        for(int i=1; i<=n-k+1; i++){
            c_min = inf;
            c_max = -inf;
            Query(i, i+k-1, 1, n, 1);
            min_ans[cnt] = c_min;
            max_ans[cnt++] = c_max;
        }

        for(int i=0; i<cnt; i++){
            if(i) printf(" ");
            printf("%d", min_ans[i]);
        }
        printf("\n");
        for(int i=0; i<cnt; i++){
            if(i) printf(" ");
            printf("%d", max_ans[i]);
        }
        printf("\n");
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值