• 普通线段树维护区间最大最小值(板子)


    /*
    线段树维护区间最大/小值就是按照原来给出的数据的顺序建造一颗二叉树,然后每一个节点维护
    这个节点的子节点且包含这个节点的值中的最大/小值
    */
    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define ll long long
    const int MAX_LEN =1000 ;
    int seg_tree[MAX_LEN << 2];
    int Lazy[MAX_LEN << 2];
    int arr[MAX_LEN];
    //从下往上更新 节点
    void push_up (int root) {
        seg_tree[root] = max(seg_tree[root << 1], seg_tree[root << 1 | 1]);      //最小值改min
    }
    //从上向下更新,左右孩子
    void push_down (int root, int L, int R) {
        if(Lazy[root]){
            Lazy[root << 1] += Lazy [root];
            Lazy[root << 1 | 1] += Lazy[root];
            int mid = (L + R) >> 1;
            seg_tree[root << 1] +=  Lazy[root] * (mid - L + 1);
            seg_tree[root << 1 | 1] += Lazy[root] * (R - mid);
            Lazy[root] = 0;
        }
    }
    //建树
    //[L,R]就是对应arr数组里面的数
    void build (int root, int L, int R) {
        Lazy[root] = 0;
        if(L == R) {
            seg_tree[root] = arr[L];
            return ;
        }
        int mid = (L + R) >> 1;
        build(root << 1, L, mid);
        build(root << 1 | 1, mid + 1, R);
        push_up(root);
    }
    
    //区间查询
    //查找区间[LL,RR]的最大/小值
    int query (int root, int L, int R, int LL, int RR) {
        if (LL <= L && R <= RR) return seg_tree[root];
        push_down(root, L, R);     //每次访问都去检查Lazy 标记
        int Ans = 0;
        int mid = (L + R) >> 1;
        if(LL <= mid) Ans = max(Ans, query(root << 1, L, mid, LL, RR));    //最小值改min
        if(RR > mid) Ans = max(Ans, query(root << 1 | 1, mid + 1, R, LL, RR)); //最小值改min
        return Ans;
    }
    //区间修改 +-某值
    //使得区间[LL,RR]的值都加上val
    void update_Interval(int root, int L, int R, int LL, int RR, int val){
         if (LL <= L && R <= RR) {
             Lazy[root] += val;
             seg_tree[root] += val * (R - L + 1);
            return ;
         }
         push_down(root, L, R);
         int mid = (L + R) >> 1;
         if (LL <= mid) update_Interval(root << 1, L, mid, LL, RR, val);
         if (RR > mid) update_Interval(root << 1 | 1, mid + 1, R, LL , RR, val);
         push_up(root);
    }
    //单点修改 可以改为某值,或者+-某值
    //把pos位置的值改成val
    void update(int root, int L, int R, int pos, int val) {
        if(L == R){
            seg_tree[root] = val;    //点直接变为某值
            return ;
        }
        int mid = (L + R) >> 1;
        if(pos <= mid) update(root << 1, L, mid, pos, val);
        else update(root << 1 | 1, mid + 1, R, pos, val);
        push_up(root);
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&arr[i]);
        }
        build(1,1,n);
        while(m--)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%d
    ",query(1,1,n,1,r));
        }
        return 0;
    }
    /*
    5 4
    3 2 4 5 1
    1 2
    2 4
    3 5
    2 3
    */
  • 相关阅读:
    如何阅读论文(译)
    Linux运维小知识
    认识Linux分区
    如何获取离线安装Chrome扩展程序的包
    Centos 7.4 下初探Zabbix安装
    尝试在Linux上部署Asp.net Core应用程序
    Centos 7.3下图文安装SQL Server
    Asp.net MVC Razor常见问题及解决方法
    轻量级高性能ORM框架:Dapper高级玩法
    Asp.net MVC 如何对所有用户输入的字符串字段做Trim处理
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/13647619.html
Copyright © 2020-2023  润新知