세그먼트 트리 (간격 수)

쓰기 사진은 여기에 설명

쓰기 사진은 여기에 설명

쓰기 사진은 여기에 설명

쓰기 사진은 여기에 설명
쓰기 사진은 여기에 설명

쓰기 사진은 여기에 설명
쓰기 사진은 여기에 설명
쓰기 사진은 여기에 설명

언어 :
균형 잡힌 라인업
시간 제한 : 5000MS 메모리 제한 : 65536k 나
총 제출 : 64,465 허용 : 30,048
케이스 시간 제한 : 2000MS
설명

매일 착유를 들어, 농부 존의 N 소 (1 ≤ N ≤ 50,000)은 항상 같은 순서로 정렬. 어느 날 농부 요한은 젖소의 일부 궁극적 인 프리스비의 게임을 구성하기로 결정합니다. 일을 간단하게 유지하기 위해, 그는 게임을 착유 라인업에서 젖소의 연속 범위를 취할 것입니다. 모든 소는 재미를위한 그러나, 그들은 높이가 너무 많은 차이가 있습니다.

농부 존 Q 목록 (1 ≤ Q ≤ 200,000) 소의 잠재적 인 그룹과 높이 (1 개 ≤ 높이 ≤ 100)을 만들었다. 각 그룹에 대해, 그는 짧고 그룹에서 가장 높은 소 사이의 높이 차이를 결정하기 위해 당신의 도움을 원한다.

입력

Line 1: Two space-separated integers, N and Q.
Lines 2..N+1: Line i+1 contains a single integer that is the height of cow i
Lines N+2..N+Q+1: Two integers A and B (1 ≤ A ≤ B ≤ N), representing the range of cows from A to B inclusive.
Output

Lines 1..Q: Each line contains a single integer that is a response to a reply and indicates the difference in height between the tallest and shortest cow in the range.
Sample Input

6 3
1
7
3
4
2
5
1 5
4 6
2 2
Sample Output

6
3
0

分析,题目要求求指定区间的最大最下值的差值,用到区间树就会更加简单,先构建树再输入数值时候可以对每个区间的最大最小值进行操作。

首先定义每个节点,必须要包括左右边界,向上取整中间值,其余需要存储的数据根据题目要求添加

구조체 데이터 / / 노드
{
INT R & LT, L;
INT MID () // 중간 반올림 값
{
창 (R & LT + L) / 2;
}
}

각 구간의 제목 필요한 최소 및 최대 값은 각각의 섹션에 추가되어야

struct data
{
    int R,L;
    int max,min;
    int mid()
    {
       return (R+L)/2;
    }
}

두 번째 단계는 범위 트리를 구축하는 것입니다

Build(int root,int R,int L)
{

        对数值进行操作
        if (r != l)
    {
        build(2*root+1,l,(r+l)/2);
        build(2 * root + 2, ((r + l) / 2) + 1, r);
    }
}

세 번째 단계 삽입

void insert(int root,int i,int v)
{
    if (p[root].l == p[root].r)
    {
        数值操作
        return;
    }
    数值操作
    if (p[root].mid() >= i)
        insert(2 * root + 1, i, v);
    else
        insert(2 * root + 2, i, v);
}

주제 코드

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int INF = 0xffffff0;//负无穷
int maxv = -INF;
int minv = INF;
struct d
{
    int r, l;
    int max, min;
    int mid()
    {
        return (l+r)/2;
    }
}p[800010];
void build(int root, int l, int r)
{
    p[root].l = l;
    p[root].r = r;
    p[root].max = -INF;
    p[root].min = INF;
    if (r != l)
    {
        build(2*root+1,l,(r+l)/2);
        build(2 * root + 2, ((r + l) / 2) + 1, r);
    }
}
void insert(int root,int i,int v)
{
    if (p[root].l == p[root].r)
    {
        p[root].max = p[root].min = v;
        return;
    }
    p[root].max = max(v, p[root].max);
    p[root].min = min(v, p[root].min);
    if (p[root].mid() >= i)
        insert(2 * root + 1, i, v);
    else
        insert(2 * root + 2, i, v);
}
void find(int root,int l,int r)
{
    if (p[root].max <= maxv && p[root].min >= minv)  //剪枝
        return;
    if (p[root].l == l&&p[root].r == r)//如果找到正好重合的区间就停止向下找
    {
        maxv = max(maxv, p[root].max);
        minv = min(minv,p[root].min);
        return;
    }
    if (p[root].mid() >= r)
        find(2 * root + 1, l, r);
    else if (p[root].mid() < l)
        find(2 * root + 2, l, r);
    else
    {
    find(2 * root + 1, l, p[root].mid());
    find(2 * root + 2, p[root].mid() + 1, r);
    }

}
int main()
{
    int n, t, m;
    int R, L;
    scanf("%d%d",&n,&t);
    build(0, 1, n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d",&m);
        insert(0,i,m);
    }
    for (int i = 1; i <= t; i++)
    {
        scanf("%d%d",&L,&R);
        minv = INF;
        maxv = -INF;
        find(0,L,R);
        printf("%d\n",maxv-minv);
    }
    return 0;
}
게시 24 개 원래 기사 · 원 찬양 5 · 조회수 3953

추천

출처blog.csdn.net/qq_41345281/article/details/81947966