线段树----logn时间维护查询区间和/最大值/最小值

news2024/11/26 14:19:54

在这里插入图片描述

线段树

引入

  • 线段树是算法竞赛中常用的用来维护 区间信息 的数据结构。

  • 线段树可以在 O(\log N) 的时间复杂度内实现单点修改、区间修改、区间查询(区间求和,求区间最大值,求区间最小值)等操作。

线段树的区间修改与懒惰标记

过程
如果要求修改区间 [l,r],把所有包含在区间 [l,r] 中的节点都遍历一次、修改一次,时间复杂度无法承受。我们这里要引入一个叫做 「懒惰标记」 的东西。

懒惰标记,简单来说,就是通过延迟对节点信息的更改,从而减少可能不必要的操作次数。每次执行修改时,我们通过打标记的方法表明该节点对应的区间在某一次操作中被更改,但不更新该节点的子节点的信息。实质性的修改则在下一次访问带有标记的节点时才进行。

仍然以最开始的图为例,我们将执行若干次给区间内的数加上一个值的操作。我们现在给每个节点增加一个 ti,表示该节点带的标记值。

2569. 更新数组后处理求和查询

给你两个下标从 0 开始的数组 nums1 和 nums2 ,和一个二维数组 queries 表示一些操作。总共有 3 种类型的操作:

操作类型 1 为 queries[i] = [1, l, r] 。你需要将 nums1 从下标 l 到下标 r 的所有 0 反转成 1 或将1 反转成 0 。l 和 r 下标都从 0 开始。 操作类型 2 为 queries[i] = [2, p, 0] 。对于 0 <= i <n 中的所有下标,令 nums2[i] = nums2[i] + nums1[i] * p 。 操作类型 3 为 queries[i] = [3, 0, 0] 。求 nums2 中所有元素的和。 请你返回一个数组,包含所有第三种操作类型的答案。

示例 1:

输入:nums1 = [1,0,1], nums2 = [0,0,0], queries = [[1,1,1],[2,1,0],[3,0,0]]
输出:[3]
解释:第一个操作后 nums1 变为 [1,1,1] 。第二个操作后,nums2 变成 [1,1,1] ,所以第三个操作的答案为 3 。所以返回 [3] 。

示例 2:

输入:nums1 = [1], nums2 = [5], queries = [[2,0,0],[3,0,0]]
输出:[5]
解释:第一个操作后,nums2 保持不变为 [5] ,所以第二个操作的答案是 5 。所以返回 [5] 。
 
提示:

1 <= nums1.length,nums2.length <= 105
nums1.length = nums2.length
1 <= queries.length <= 105
queries[i].length = 3
0 <= l <= r <= nums1.length - 1
0 <= p <= 106
0 <= nums1[i] <= 1
0 <= nums2[i] <= 109
class Node {
    int l, r;
    int s, lazy;
}

class SegmentTree {
    private Node[] tr;
    private int[] nums;

    public SegmentTree(int[] nums) {
        int n = nums.length;
        this.nums = nums;
        tr = new Node[n << 2];
        for (int i = 0; i < tr.length; ++i) {
            tr[i] = new Node();
        }
        build(1, 1, n);
    }

    private void build(int u, int l, int r) {
        tr[u].l = l;
        tr[u].r = r;
        if (l == r) {
            tr[u].s = nums[l - 1];
            return;
        }
        int mid = (l + r) >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
        pushup(u);  //左右子树之和为当前节点的值s
    }

    public void modify(int u, int l, int r) {
        if (tr[u].l >= l && tr[u].r <= r) {
            tr[u].lazy ^= 1;
            tr[u].s = tr[u].r - tr[u].l + 1 - tr[u].s;
            return;
        }
        pushdown(u);
        int mid = (tr[u].l + tr[u].r) >> 1;
        if (l <= mid) {
            modify(u << 1, l, r);
        }
        if (r > mid) {
            modify(u << 1 | 1, l, r);
        }
        pushup(u);
    }

    public int query(int u, int l, int r) {
        if (tr[u].l >= l && tr[u].r <= r) {
            return tr[u].s;
        }
        pushdown(u);
        int mid = (tr[u].l + tr[u].r) >> 1;
        int res = 0;
        if (l <= mid) {
            res += query(u << 1, l, r);
        }
        if (r > mid) {
            res += query(u << 1 | 1, l, r);
        }
        return res;
    }

    private void pushup(int u) {
        tr[u].s = tr[u << 1].s + tr[u << 1 | 1].s;
    }

    private void pushdown(int u) {
        if (tr[u].lazy == 1) {
            int mid = (tr[u].l + tr[u].r) >> 1;
            tr[u << 1].s = mid - tr[u].l + 1 - tr[u << 1].s;
            tr[u << 1].lazy ^= 1;
            tr[u << 1 | 1].s = tr[u].r - mid - tr[u << 1 | 1].s;
            tr[u << 1 | 1].lazy ^= 1;
            tr[u].lazy ^= 1;
        }
    }
}

class Solution {
    public long[] handleQuery(int[] nums1, int[] nums2, int[][] queries) {
        SegmentTree tree = new SegmentTree(nums1);
        long s = 0;
        for (int x : nums2) {
            s += x;
        }
        int m = 0;
        for (var q : queries) {
            if (q[0] == 3) {
                ++m;
            }
        }
        long[] ans = new long[m];
        int i = 0;
        for (var q : queries) {
            if (q[0] == 1) {
                tree.modify(1, q[1] + 1, q[2] + 1);
            } else if (q[0] == 2) {
                s += 1L * q[1] * tree.query(1, 1, nums2.length);
            } else {
                ans[i++] = s;
            }
        }
        return ans;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/796539.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Day44 算法记录| 动态规划 10 (股票问题)

股票问题 123.买卖股票的最佳时机III188. 买卖股票的最佳时机 IV 123.买卖股票的最佳时机III 方法一&#xff1a;二维数组的讲解&#xff1a; class Solution {public int maxProfit(int[] prices) {int day prices.length;int[][] dp new int[day][5];//初始化dp[0][1] -p…

教你使用PHP实现一个轻量级HTML模板引擎

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;2023年6月csdn上海赛道top4。多年电商行业从业经验&#xff0c;对系统架构&#xff0c;数据分析处理等大规模应用场景有丰富经验。 &#x1f3c6;本文已收录于PHP专栏&#xff1a;PHP…

Ubuntu系统下:write_frames() got an unexpected keyword argument ‘audio_path‘

在部署Datid3d项目是遇到了一个imageio_ffmpeg的报错问题&#xff0c;网上也没有解决办法&#xff0c;在github上查看这个开源库时发现这个库的0.4.3和0.4.8的版本有差别&#xff0c;具体情况如下图&#xff1a; 0.4.3版本&#xff1a; 0.4.8版本&#xff1a; 我原先装得的是0…

AD 封装组件的水平/垂直间距报错

快捷键&#xff1a;D设计→R规则 一般情况下设置的都是&#xff1a;Electrical 下的Clearance 但是设置完了还是继续报错 是封装之间的水平间距问题 应该设置Placement 下的ComponentClearance

某网站搜索接口参数MD5加密又加盐逆向实战分析

1. 写在前面 最近在写爬虫的时候发现一些小网站上的MD5加密&#xff0c;在我们团队开发的千把个网站爬虫内发现这种MD5加密的案例还不少&#xff01;话不多说&#xff0c;直接拿出来分析一波 之后我准备抽时间总结出一个关于如何快速搜索与定位JS加密函数与分析与辨别常见加密…

dockerfile健康检查HEALTHCHECK

1、dockerfile示例 FROM registry.access.redhat.com/ubi9/ubi-init #关闭订阅管理器功能,便于使用dnf安装软件RUN sed -i s/d1/d0/ /etc/yum/pluginconf.d/subscription-manager.conf RUN curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos…

【前端知识】JavaScript——5个迭代函数:every、filter、forEach、map、some

【前端知识】JavaScript——5个迭代函数&#xff1a;every、filter、forEach、map、some JavaScript高级程序设计(第4版)&#xff1a;ECMAScript 为数组定义了 5 个迭代方法。每个方法接收两个参数&#xff1a;以每一项为参数运行的函数&#xff0c;以及可选的作为函数运行上下…

心率血氧传感器方案

JFH142多光谱健康监测模块&#xff0c;无创采集人体的脉搏波&#xff0c;用户系统只需通过串口即可和模块通信&#xff0c;并且直接获得测量结果&#xff0c;为用户输出实时连续的心率、血氧、血管弹性等健康数据&#xff0c;并通过云端服务器的大数据平台将脉搏波数据进行算法…

双目视觉,立体视觉,双目标定,三维重建,深度估计,棋盘格,RAFTStereo,HitNet,深度估计

github:https://github.com/pcb9382/StereoAlgorithms gitee:https://gitee.com/peng-chuanbo/StereoAlgorithms StereoAlgorithms 简体中文 | English 如果觉得有用&#xff0c;不妨给个Star⭐️&#x1f31f;支持一下吧~ 谢谢&#xff01; Acknowledgments & Contact…

解决IDEA的git非常缓慢方法

解决IDEA的git非常缓慢方法 xxxx\IDEA2021.1.3\IntelliJ IDEA 2021.1.3\bin

2023最新Ubuntu安装部署Gitlab详细教程(每个步骤均配图)

Ubuntu安装配置Gitlab详细步骤 安装依赖 打开终端&#xff0c;运行如下命令&#xff1a; sudo apt updatesudo apt-get upgradesudo apt-get install curl openssh-server ca-certificates postfix接下来会遇到如下界面&#xff0c;Tab切换到“确定”按钮&#xff0c;然后回…

ThinkPHP8知识详解:ThinkPHP8是什么?

欢迎你来到PHP服务网学习最新的ThinkPHP8开发教程&#xff0c;本文介绍一下ThinkPHP8是什么&#xff1f; 1、ThinkPHP8是ThinkPHP框架的最新版本&#xff0c;它在之前版本的基础上进行了改进和优化。它采用了现代化的设计理念和架构&#xff0c;提供了更好的性能和更丰富的功能…

GRE TAP的工作原理与5G工业物联网中的应用

随着互联网新技术的发展以及智能化水平的提高&#xff0c;各企业对实时数据传输的需求也在不断提升&#xff0c;企业愈发重视数据中心的建设&#xff0c;以保障企业内网数据安全。 GRE&#xff08;Generic Routing Encapsulation&#xff0c;通用路由封装&#xff09;协议属于…

opencv-26 图像几何变换04- 重映射-函数 cv2.remap()

什么是重映射&#xff1f; 重映射&#xff08;Remapping&#xff09;是图像处理中的一种操作&#xff0c;用于将图像中的像素从一个位置映射到另一个位置。重映射可以实现图像的平移、旋转、缩放和透视变换等效果。它是一种基于像素级的图像变换技术&#xff0c;可以通过定义映…

vue项目中对组件使用v-model绑定值,在vue3中如何更新数据

在el-form 中 el-form-item 绑定组件进行校验 想在表单下面爆红提示 可以对组件使用v-model绑定值 vue2 通过this.$emit(‘input’,value) 更新 v-model值 vue3 通过this.$emit(‘update:modelValue’ ,value) 更新 v-model值

管理类联考——写作——素材篇——论说文——人工智能

有人说&#xff0c;机器人的使命应该是帮助人类做那些人类做不了的事情&#xff0c;而不是替代人类。技术变革会夺取一些人低端繁琐的工作岗位&#xff0c;最终也会创造更高端更人性化的工作机会。例如&#xff0c;铁路的出现抢去了很多挑夫的工作&#xff0c;但也增加了千百万…

资源成本降低70%!华为MetaERP资产核算的Serverless架构实践

资产核算是指在一定的财务周期&#xff0c;对企业拥有的房屋建筑物、机器设备、商标权和专利权等资产的取得、折旧和处置的会计核算&#xff0c;反映企业固定资产、无形资产的增减变动和价值分摊活动。华为资产核算产品&#xff0c;支撑企业资产从获取到处置全生命周期的管理和…

synchronized关键字同步原理

1.同步方法 public class Test {synchronized public static void testMethod(){}public static void main(String[] args) {testMethod();} }// 实现class文件的反汇编 java -c -v *.class从字节码文件中可以看到同步方法根据flags标志中的ACC_SYNCHRONIZED来判别是否是同步方…

动态内存管理面试题

动态内存管理面试题 文章目录 动态内存管理面试题一、第一题此代码存在的问题运行结果分析原因修改 二、第二题此代码存在的问题运行结果分析原因修改 一、第一题 代码如下&#xff08;示例&#xff09;&#xff1a; #include<stdio.h> #include<string.h> #incl…

快速学习Protobuf

目录 1. 什么是Protobuf&#xff1f; 2. 安装与设置 3. 定义消息 4. 编写.proto文件 5. 编译.proto文件 6. 序列化与反序列化 7. 使用Proto文件 8. Protobuf高级特性 1. 什么是Protobuf&#xff1f; 简介&#xff1a;Protobuf&#xff08;Protocol Buffers&#xff09;…