kuangbin line segment tree-HDU-1754 I Hate It (line segment tree single point modification template question)

kuangbin line segment tree-HDU-1754 I Hate It (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

A habit of comparison is popular in many schools. Teachers like to ask, from XX to XX, what is the highest score. This makes many students disgusted.

Whether you like it or not, what you need to do now is to write a program according to the teacher's request to simulate the teacher's inquiry. Of course, teachers sometimes need to update a classmate's grades.

Input

This question contains multiple sets of tests, please process until the end of the file. In the first line of each test, there are two positive integers N and M (0<N<=200000, 0<M<5000), which represent the number of students and the number of operations, respectively. The student ID numbers are numbered from 1 to N.
The second line contains N integers, representing the initial scores of these N students, where the i-th number represents the score of the student with ID i. There are M rows next. Each line has a character C
(take only'Q' or'U'), and two positive integers A and B.
When C is'Q', it means that this is a query operation. It asks the students whose ID is from A to B (including A and B), what is the highest score.
When C is'U', it means that this is an update operation, requiring the student whose ID is A to be changed to B.

Output

For each query operation, output the highest score in one line.

Sample Input

5 6
1 2 3 4 5
Q 1 5
U 3 6
Q 3 4
Q 4 5
U 2 9
Q 1 5

Sample Output

5
6
5
9

This question is about the maximum value in the query interval. Just
understand the single-point modification of the line segment tree (and the code has a detailed explanation)
. For the single-point modification of the line segment tree, you can check this article (there is a template question HDU-1166 enemy troops layout and diagram Detailed text):
Knowledge points related to the line segment tree and template question HDU-1166 enemy 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 = 200010;

int m, p;//m操作次数,p取模的值是多少
struct Node{
    
    
    int l, r;//左端点,右端点
    int val;//区间[l, r]的最大值
}tr[N << 2];
int num[N];

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

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

//[l, r]查询区间   cur代表当前线段树里面的端点。
int query(int cur, int l, int r) {
    
    
    
    //①情况[TL,TR] ⊂ [L,R]
    //树中节点,已经被完全包含在[l, r]中了。
    if (tr[cur].l >= l && tr[cur].r <= r) {
    
    
        return tr[cur].val;
    }
    
    int mid = tr[cur].l + tr[cur].r >> 1;
    int val = 0;
    
    //判断与左边有没有交集
    if (l <= mid) {
    
    
        val = query(cur << 1, l, r);
    }
    
    //这里为什么是 r > mid,因为划分的区间是[l, mid][mid + 1, r],所以要用>而不能=
    //判断与右边有没有交集
    if (r > mid) {
    
    
        //为什么要取max?
        //因为上面先比较左值,所以左值可能有一个最大值,要跟再右边区间查询的值进行比较,取最大的。
        val = max(val, query(cur << 1 | 1, l, r));
    }
    //返回结果
    return val;
}

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

int main()
{
    
    
    int n,m;
    while(~scanf("%d%d",&n,&m)){
    
    
        memset(num, 0, sizeof num);
        memset(tr, 0, sizeof tr);
        for (int i = 1;i <= n; ++i) {
    
    
            scanf("%d", &num[i]);
        }
        build(1, 1, n);
        for (int i = 0; i < m; ++i) {
    
    
            char ch;
            int a, b;
            getchar();//每一次都要getchar();放在循环里面的第一行。
            scanf("%c%d%d",&ch,&a,&b);

            if (ch == 'Q') {
    
    
                printf("%d\n", query(1, a, b));
            }
            else{
    
    
                modify(1, a, b);
            }
        }
    }
    return 0;
}

Guess you like

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