kuangbin line segment tree-POJ-3264 Balanced Lineup (line segment tree single point modification template question)

kuangbin line segment tree-POJ-3264 Balanced Lineup (line segment tree single point modification template question)

General question sheet week 3 [kuangbin takes you to fly] Question sheet minimum spanning tree + line segment tree Click here ~~
https://blog.csdn.net/m0_46272108/article/details/108980362

Descriptions:

For the daily milking, Farmer John’s N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer John decides to organize a game of Ultimate Frisbee with some of the cows. To keep things simple,
he will take a contiguous range of cows from the milking lineup to
play the game. However, for all the cows to have fun they should not differ too much in height.
Farmer John has made a list of Q (1 ≤ Q ≤ 200,000) potential groups of cows and their heights (1 ≤ height ≤ 1,000,000). For each group, he wants your help to determine the difference in height between the shortest and the tallest cow in the group.

Title description

N (1≤N≤50000) trees in a piece of green space are lined up in a row. On a nice afternoon, the gardener received a task to trim the N trees. The gardener already knew the height of the N trees H (1 ≤ height ≤ 1000000) (1≤height≤1000000)(1height1 0 0 0 0 0 0 ) . The task of the garden master street isQ (1 ≤ Q ≤ 200000) Q (1≤Q≤200000)Q(1Q2 0 0 0 0 0 ) small tasks. For each small task, the gardener must know the height difference between the tallest tree and the shortest tree in a specific interval. The gardener does not know how to calculate. This task is a bit difficult for him. Can you help him?

Input

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.
第一行为 N ( 1 ≤ N ≤ 50000 ) N(1≤N≤50000) N(1N5 0 0 0 0 ) andQ (1 ≤ Q ≤ 200000) Q (1≤Q≤200000)Q(1Q2 0 0 0 0 0 ) ;. From line 2 to line N+1, each line has a number,
indicating the height of the i-th tree(1 ≤ height ≤ 1000000) (1≤height≤1000000)(1height1 0 0 0 0 0 0 ) ; From row N+2 to row N+Q+1, each row has two integers A and B(1 ≤ A ≤ B ≤ N) (1≤A≤B≤N)(1ABN ) , which
means all the trees in the interval from the Ath tree to the Bth tree.

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.

From the first row to the Qth row, each row has an integer, which represents the height difference between the tallest tree and the shortest tree from the Ath tree to the Bth tree.

Sample Input

6 3
1
7
3
4
2
5
1 5
4 6
2 2

Sample Output

6
3
0

This question is to query the difference between the maximum and minimum values ​​in the interval (just open two variables) to
understand the single-point modification of the line segment tree (and the code is explained in detail) For
the single-point modification of the line segment tree, you can view this article ( There is a template question HDU-1166 enemy troops formation and detailed graphic explanations):
knowledge points about the line segment tree and template question HDU-1166 enemy troops formation: https://blog.csdn.net/m0_46272108/article/details/108955623

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<algorithm>

#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long
//#define int ll
#define inf 0x3f3f3f3f
using namespace std;
int read()
{
    
    
	int w = 1, s = 0;
	char ch = getchar();
	while (ch < '0' || ch>'9') {
    
     if (ch == '-') w = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') {
    
     s = s * 10 + ch - '0';    ch = getchar(); }
	return s * w;
//最大公约数
}int gcd(int x,int y) {
    
    
    if(x<y) swap(x,y);//很多人会遗忘,大数在前小数在后
    //递归终止条件千万不要漏了,辗转相除法
    return x % y ? gcd(y, x % y) : y;
}
int lcm(int x,int y)//计算x和y的最小公倍数
{
    
    
    return x * y / gcd(x, y);//使用公式
}
//------------------------ 以上是我常用模板与刷题几乎无关 ------------------------//

const int N = 50010;
int Maxval, Minval;
struct Node{
    
    
    int l, r;//左端点,右端点
    int Maxval;//区间[l, r]的最大值
    int Minval;//区间[l, r]的最小值
}tr[N << 2];

//由子节点的信息来计算父节点的信息
void pushup(int cur, int val){
    
    
    tr[cur].Maxval = max(tr[cur].Maxval, val);
    tr[cur].Minval = min(tr[cur].Minval, val);
}

//cur代表当前节点,
void build(int cur, int l, int r){
    
    
    //当前结点的左右儿子分别是tr[cur].l   tr[cur].r
    tr[cur] = {
    
    l, r};
    //如果已经是叶结点return
    
    tr[cur].Minval = inf;
    tr[cur].Maxval = -inf;
    //求一下当前区间的中点
    int mid = l + r >> 1;
    
    if(l == r) {
    
    
        return;
    } else {
    
    
        //递归建立左边区间
    build(cur << 1, l, mid);
    //递归建立右边区间
    build(cur << 1 | 1, mid + 1, r);
    // pushup(cur);
    }
}

//[l, r]查询区间   cur代表当前线段树里面的端点。
void query(int cur, int l, int r) {
    
    
    
    if(tr[cur].Maxval <= Maxval && tr[cur].Minval >= Minval) 
        return;
    //①情况[TL,TR] ⊂ [L,R]
    //树中节点,已经被完全包含在[l, r]中了。
    if (tr[cur].l >= l && tr[cur].r <= r) {
    
    
        Minval = min(tr[cur].Minval, Minval);
        Maxval = max(tr[cur].Maxval, Maxval);
        return;
    }
    
    int mid = tr[cur].l + tr[cur].r >> 1;
    
    //判断与左边有没有交集
    if (r <= mid) {
    
    
        query(cur << 1, l, r);
    } else if (l > mid) {
    
    
    //这里为什么是 r > mid,因为划分的区间是[l, mid][mid + 1, r],所以要用>而不能=
    //判断与右边有没有交集
        //为什么要取max?
        query(cur << 1 | 1, l, r);
    } else {
    
    
        query(cur << 1, l, r);
        query(cur << 1 | 1, l, r);
    }
}

//cur代表当前线段树里面的端点。tar代表要修改的位置
void modify(int cur, int tar, int val) {
    
    
    int l = tr[cur].l, r = tr[cur].r;
    //如果当前节点就是叶节点,那么直接修改就可以了
    if (tr[cur].l == tar && tr[cur].r == tar) {
    
    
        tr[cur].Maxval = val;
        tr[cur].Minval = val;
        return;
    }
    int mid = l + r >> 1;
    if (tar <= mid) {
    
    
        modify (cur << 1, tar, val);
    } else {
    
    
        modify (cur << 1 | 1, tar, val);
    }
    //递归完之后,要更新到父节点。
    //pushup就是更新父节点的信息
    pushup(cur, val);
}

int main()
{
    
    
    int n, q;
    int a, b;
    while (~scanf("%d%d", &n, &q)) {
    
    
        build(1, 1, n);
        for (int i = 1; i <= n; ++i) {
    
    
            a = read();
            modify(1, i, a);
        }
        for (int i = 1; i <= q; ++i) {
    
    
            a = read(), b = read();
            Minval = inf, Maxval = -inf;
            query(1, a, b);
            printf("%d\n", Maxval - Minval);
        }
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/m0_46272108/article/details/108962485