POJ 3264

POJ 3264
线段树题目

题目链接:http://poj.org/problem?id=3264

题目大意:在一个区间内找到最大值与最小值之间的差值。

#include <iostream>
using namespace std;

struct P{
    int mm, nn, left, right;
    // mm指该节点的最大值, nn指该节点的最小值, left指该线段树节点的范围最小值, left指该线段树节点的范围最大值
};
int d[50005],n,q,mmm=0,nnn=1000000;
// mmm存储每次访问区间的最大值, nnn存储每次访问区间的最小值
P dat[200005];  //存储线段树

void init(int k, int l, int r) {    //建立线段树
    if (r - l == 0) {
        dat[k].nn = d[l];
        dat[k].mm = d[l];
        dat[k].left = l;
        dat[k].right = l;
    }
    else {
        int ll = k * 2 + 1, rr = k * 2 + 2, mid = (l + r) / 2;
        if ((l + r) % 2 == 1) {
            mid = (l + r) / 2;
            init(ll, l, mid);
            init(rr, mid + 1, r);
        }
        else {
            mid = (l + r) / 2;
            init(ll, l, mid - 1);
            init(rr, mid, r);
        }
        dat[k].nn = min(dat[ll].nn, dat[rr].nn);
        dat[k].mm = max(dat[ll].mm, dat[rr].mm);
        dat[k].left = l;
        dat[k].right = r;
    }
}

void solve(int a, int b, int k) {   
    if (a >= dat[k].left && b <= dat[k].right) {
        if (a == dat[k].left && b == dat[k].right) {
            mmm = max(mmm, dat[k].mm);
            nnn = min(nnn, dat[k].nn);
            return;
        }
        solve(max(a, dat[k].left), min(b, dat[k].right), 2 * k + 1);
        solve(max(a, dat[k].left), min(b, dat[k].right), 2 * k + 2);
    }
    if (b > dat[k].right) {
        if (a == dat[k].left) {
            mmm = max(mmm, dat[k].mm);
            nnn = min(nnn, dat[k].nn);
            return;
        }
        if (a > dat[k].right) {
            return;
        }
        else {
            solve(max(a, dat[k].left), min(b, dat[k].right), 2 * k + 1);
            solve(max(a, dat[k].left), min(b, dat[k].right), 2 * k + 2);
        }
    }
    if (a < dat[k].left) {
        if (b == dat[k].right) {
            mmm = max(mmm, dat[k].mm);
            nnn = min(nnn, dat[k].nn);
            return;
        }
        if (b < dat[k].left) {
            return;
        }
        else {
            solve(max(a, dat[k].left), min(b, dat[k].right), 2 * k + 1);
            solve(max(a, dat[k].left), min(b, dat[k].right), 2 * k + 2);
        }
    }
}

int main() {
    int a,b;
    scanf("%d %d", &n, &q);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &d[i]);
    }
    init(0, 1, n);
    while(q--) {
        mmm=0,nnn=1000000;
        scanf("%d %d", &a, &b);
        solve(a, b, 0);
        printf("%d\n",mmm-nnn);
    }
    return 0;
}

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值