Acwing: 一道关于线段树的好题(有助于全面理解线段树)

news2025/8/2 11:09:28

题目链接🔗:2643. 序列操作 - AcWing题库

前驱知识:需要理解线段树的结构和程序基本框架、以及懒标记的操作。

题目描述

题目分析 

对区间在线进行修改和查询,一般就是用线段树来解决,观察到题目一共有五个操作

我们首先要思考需要用线段树维护哪些信息,通过维护这些信息,在查询时能够得到需要的答案。

根据查询的内容,我们发现需要维护区间内1的个数sum1,以及区间内最多连续1的个数m1

由于题目的操作对象就是0和1,我们可以想到对称维护0和1的信息(主要是因为存在操作2

那么综合来看,我们可以维护线段树的以下信息:

l :区间左端点

r :区间右端点

sum1 :区间内1的个数

sum0 :区间内0的个数

l1 :区间内左边最多连续1的个数

l0 :区间内左边最多连续0的个数

r1 :区间内右边最多连续1的个数

r0 :区间内右边最多连续0的个数

m0 :区间内最长连续0的个数

m1:区间内最长连续1的个数

flag0 :操作0对应的懒标记

flag1 :操作1对应的懒标记

rev :操作2对应的懒标记


具体维护方案如下

AC代码 

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std ;

const int N = 1e5 + 10 ; 

int n, m, a[N] ; 
struct Node 
{
    int l, r ; 
    int sum0, sum1, l0, l1, r0, r1, m0, m1 ; 
    bool flag0, flag1, rev ; 
}tr[4 * N] ; 

void pushup(int u) 
{
    tr[u].sum0 = tr[u << 1].sum0 + tr[u << 1 | 1].sum0 ; 
    tr[u].sum1 = tr[u << 1].sum1 + tr[u << 1 | 1].sum1 ;
    tr[u].l0 = (tr[u << 1].sum1) ? tr[u << 1].l0 : tr[u << 1].sum0 + tr[u << 1 | 1].l0 ;
    tr[u].l1 = (tr[u << 1].sum0) ? tr[u << 1].l1 : tr[u << 1].sum1 + tr[u << 1 | 1].l1 ;
    tr[u].r0 = (tr[u << 1 | 1].sum1) ? tr[u << 1 | 1].r0 :  tr[u << 1 | 1].sum0 + tr[u << 1].r0 ; 
    tr[u].r1 = (tr[u << 1 | 1].sum0) ? tr[u << 1 | 1].r1 :  tr[u << 1 | 1].sum1 + tr[u << 1].r1 ;
    tr[u].m0 = max(max(tr[u << 1].m0, tr[u << 1 | 1].m0), tr[u << 1].r0 + tr[u << 1 | 1].l0) ;
    tr[u].m1 = max(max(tr[u << 1].m1, tr[u << 1 | 1].m1), tr[u << 1].r1 + tr[u << 1 | 1].l1) ;
}

void pushup_Node(Node &root, Node ls, Node rs) 
{
    root.sum0 = ls.sum0 + rs.sum0 ; 
    root.sum1 = ls.sum1 + rs.sum1 ; 
    root.l0 = (ls.sum1) ? ls.l0 : ls.sum0 + rs.l0 ; 
    root.l1 = (ls.sum0) ? ls.l1 : ls.sum1 + rs.l1 ; 
    root.r0 = (rs.sum1) ? rs.r0 : rs.sum0 + ls.r0 ; 
    root.r1 = (rs.sum0) ? rs.r1 : rs.sum1 + ls.r1 ;
    root.m0 = max(max(ls.m0, rs.m0), ls.r0 + rs.l0) ; 
    root.m1 = max(max(ls.m1, rs.m1), ls.r1 + rs.l1) ;
}

void pushdown(int u) 
{
    if (tr[u].flag0) 
    {
        tr[u << 1].sum0 = tr[u << 1].l0 = tr[u << 1].r0 = tr[u << 1].m0 = tr[u << 1].r - tr[u << 1].l + 1 ; 
        tr[u << 1 | 1].sum0 = tr[u << 1 | 1].l0 = tr[u << 1 | 1].r0 = tr[u << 1 | 1].m0 = tr[u << 1 | 1].r - tr[u << 1 | 1].l + 1 ;
        tr[u << 1].sum1 = tr[u << 1].l1 = tr[u << 1].r1 = tr[u << 1].m1 = 0 ; 
        tr[u << 1 | 1].sum1 = tr[u << 1 | 1].l1 = tr[u << 1 | 1].r1 = tr[u << 1 | 1].m1 = 0 ; 
        tr[u << 1].flag0 = tr[u << 1 | 1].flag0 = true ; 
        tr[u << 1].flag1 = tr[u << 1 | 1].flag1 = tr[u << 1].rev = tr[u << 1 | 1].rev = false ;
        tr[u].flag0 = false ; 
    }
    if (tr[u].flag1) {
        tr[u << 1].sum1 = tr[u << 1].l1 = tr[u << 1].r1 = tr[u << 1].m1 = tr[u << 1].r - tr[u << 1].l + 1 ; 
        tr[u << 1 | 1].sum1 = tr[u << 1 | 1].l1 = tr[u << 1 | 1].r1 = tr[u << 1 | 1].m1 = tr[u << 1 | 1].r - tr[u << 1 | 1].l + 1 ;
        tr[u << 1].sum0 = tr[u << 1].l0 = tr[u << 1].r0 = tr[u << 1].m0 = 0 ;
        tr[u << 1 | 1].sum0 = tr[u << 1 | 1].l0 = tr[u << 1 | 1].r0 = tr[u << 1 | 1].m0 = 0 ;
        tr[u << 1].flag1 = tr[u << 1 | 1].flag1 = true ;
        tr[u << 1 | 1].flag0 = tr[u << 1 | 1].flag0 = tr[u << 1].rev = tr[u << 1 | 1].rev = false ;
        tr[u].flag1 = false ;
    }
    if (tr[u].rev) 
    {
        swap(tr[u << 1].sum0, tr[u << 1].sum1) ;
        swap(tr[u << 1 | 1].sum0, tr[u << 1 | 1].sum1) ;
        
        swap(tr[u << 1].l0, tr[u << 1].l1) ; 
        swap(tr[u << 1 | 1].l0, tr[u << 1 | 1].l1) ;
        
        swap(tr[u << 1].r0, tr[u << 1].r1) ; 
        swap(tr[u << 1 | 1].r0, tr[u << 1 | 1].r1) ;
        
        swap(tr[u << 1].m0, tr[u << 1].m1) ; 
        swap(tr[u << 1 | 1].m0, tr[u << 1 | 1].m1) ;
        
        tr[u << 1].rev ^= 1, tr[u << 1 | 1].rev ^= 1 ; 
        tr[u].rev = 0 ;
    }
}

void build(int u, int l, int r) 
{
    tr[u].l = l, tr[u].r = r ; 
    if (l == r) 
    {
        tr[u].sum0 = tr[u].l0 = tr[u].r0 = tr[u].m0 = a[r] ^ 1 ; 
        tr[u].sum1 = tr[u].l1 = tr[u].r1 = tr[u].m1 = a[r] & 1 ; 
        return ; 
    }
    int mid = l + r >> 1 ;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r) ; 
    pushup(u) ; 
}

void change1(int u, int l, int r) 
{
    if (tr[u].l >= l && tr[u].r <= r) 
    {
        tr[u].sum1 = tr[u].l1 = tr[u].r1 = tr[u].m1 = 0 ; 
        tr[u].sum0 = tr[u].l0 = tr[u].r0 = tr[u].m0 = tr[u].r - tr[u].l + 1 ; 
        tr[u].flag0 = true, tr[u].flag1 = tr[u].rev = false ;
        return ;
    }
    pushdown(u) ; 
    int mid = tr[u].l + tr[u].r >> 1 ; 
    if (l <= mid) change1(u << 1, l, r) ; 
    if (r > mid) change1(u << 1 | 1, l, r) ; 
    pushup(u) ;
}

void change2(int u, int l, int r) 
{
    if (tr[u].l >= l && tr[u].r <= r) 
    {
        tr[u].sum0 = tr[u].l0 = tr[u].r0 = tr[u].m0 = 0 ; 
        tr[u].sum1 = tr[u].l1 = tr[u].r1 = tr[u].m1 = tr[u].r - tr[u].l + 1 ; 
        tr[u].flag1 = true, tr[u].flag0 = tr[u].rev = false ;
        return ;
    }
    pushdown(u) ; 
    int mid = tr[u].l + tr[u].r >> 1 ; 
    if (l <= mid) change2(u << 1, l, r) ; 
    if (r > mid) change2(u << 1 | 1, l, r) ; 
    pushup(u) ; 
}

void Reverse(int u, int l, int r) 
{
    if (tr[u].l >= l && tr[u].r <= r) 
    {
        swap(tr[u].sum0, tr[u].sum1) ; 
        swap(tr[u].l0, tr[u].l1) ; 
        swap(tr[u].r0, tr[u].r1) ; 
        swap(tr[u].m0, tr[u].m1) ; 
        tr[u].rev ^= 1 ; 
        return ; 
    }
    pushdown(u) ; 
    int mid = tr[u].l + tr[u].r >> 1 ; 
    if (l <= mid) Reverse(u << 1, l, r) ; 
    if (r > mid) Reverse(u << 1 | 1, l, r) ;
    pushup(u) ; 
}

int ask1(int u, int l, int r) 
{
    if (tr[u].l >= l && tr[u].r <= r) return tr[u].sum1 ; 
    
    pushdown(u) ; 
    int mid = tr[u].l + tr[u].r >> 1 ; 
    int sum = 0 ; 
    if (l <= mid) sum = ask1(u << 1, l, r) ; 
    if (r > mid) sum += ask1(u << 1 | 1, l, r) ; 
    
    return sum ;
}

Node ask2(int u, int l, int r) 
{
    if (tr[u].l >= l && tr[u].r <= r) return tr[u] ; 
    
    pushdown(u) ; 
    int mid = tr[u].l + tr[u].r >> 1 ; 
    
    Node res ; 
    if (l > mid) return ask2(u << 1 | 1, l, r) ; 
    if (r <= mid) return ask2(u << 1, l, r) ; 
    
    Node ls = ask2(u << 1, l, r), rs = ask2(u << 1 | 1, l, r) ; 
    pushup_Node(res, ls, rs) ; 
    
    return res ; 
}

int main() 
{
    ios::sync_with_stdio(false) ; 
    cin >> n >> m ; 
    for (int i = 1 ; i <= n ; i ++ ) 
        cin >> a[i] ;
        
    build(1, 1, n) ; 
    
    while (m -- ) 
    {
        int opt, l, r ; 
        cin >> opt >> l >> r ; 
        l ++, r ++ ; 
        
        if (opt == 0) change1(1, l, r) ; 
        else if (opt == 1) change2(1, l, r) ; 
        else if (opt == 2) Reverse(1, l, r) ; 
        else if (opt == 3) cout << ask1(1, l , r) << endl ;
        else cout << ask2(1, l, r).m1 << endl ; 
    }

    return 0 ; 
}

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

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

相关文章

查看python第三方库的依赖pkgs

课题组的服务器不给连外网&#xff0c;安装python第三方库就只能手动离线安装。但是python第三方库可能会迭代依赖&#xff0c;单纯的pip show [pkg]是看不出来的…… 参考链接&#xff1a;查看python第三方库的依赖 https://blog.csdn.net/qq_38316655/article/details/127943…

【多层交叉transformer:高光谱和多光谱图像融合】

MCT-Net: Multi-hierarchical cross transformer for hyperspectral and multispectral image fusion &#xff08;MCT-Net&#xff1a;用于高光谱和多光谱图像融合的多层交叉transformer&#xff09; 考虑到光学成像的局限性&#xff0c;图像采集设备通常在空间信息和光谱信…

04-SQL基础(表管理,约束,多表连接,子查询)

本文章主要内容 1、表的管理&#xff1a;创建表&#xff0c;修改表结构&#xff0c;删除字段&#xff0c;修改字段&#xff0c;添加字段&#xff0c;删除表&#xff0c;添加表约束&#xff1b; 2、数据管理&#xff1a;新增记录&#xff0c;修改记录&#xff0c;删除记录&…

分享10个不错的C语言开源项目

今天跟大家分享10个重量级的C语言开源项目&#xff0c;C语言确实经得住考验&#xff1a; Redis&#xff1a;Redis是一个开源的高性能的键值对数据库。它以C语言编写&#xff0c;具有极高的性能和可靠性。 Nginx&#xff1a;Nginx是一个高性能的HTTP和反向代理服务器&#xff0…

KPN对任意形状文本检测

文章目录一、研究背景二、方法流程1. 特征提取2. 核建议3. 实例无关特征图4. 轮廓生成5. 其余部分内容三、不足一、研究背景 相比起基于 FCN 网络的文本边缘检测网络&#xff0c;KPN网络可以更好地处理文本之间的间隔。 二、方法流程 1. 特征提取 FCN 和 FPN FCN(全卷积神经…

第十四届蓝桥杯第三期模拟赛原题与详解

​​​​​​​ 文章目录 一、填空题 1、1 找最小全字母十六进制数 1、1、1 题目描述 1、1、2 题解关键思路与解答 1、2 给列命名 1、2、1 题目描述 1、2、2 题解关键思路与解答 1、3 日期相等 1、3、1 题目描述 1、3、2 题解关键思路与解答 1、4 乘积方案数 1、4、1 题目描…

在IC行业,什么样的人才能拿到高薪资offer?

最近几年国家大战略发展半导体产业&#xff0c;薪资也水涨船高&#xff0c;IC设计类岗位应届生薪水甚至已经到30W的级别&#xff0c;越来越多的人想要从事IC行业。 在IC行业&#xff0c;什么样的人才能拿到高薪资offer&#xff1f;来听听资深工程师怎么说&#xff1f; 我参加…

【网络篇】----- 传输层协议 之 UDP(协议格式,协议特性和编程影响三方面详细分析)

文章目录 前言1、UDP协议2、协议格式 2.1、协议格式模型2.2、字段分析3.协议特性4.编程影响总结前言 1、UDP协议 UDP协议&#xff0c;又名数据报传输协议&#xff0c;是传输层协议之一&#xff01;&#xff01;&#xff01; 在TCP/IP五层模型中&#xff0c;在传输层中&#xff…

MATLAB | 如何绘制github同款日历热力图

应粉丝要求&#xff0c;出一个类似于github热图的日历热力图&#xff0c;大概长这样&#xff1a; 依旧工具函数放在文末&#xff0c;如有bug请反馈并去gitee下载更新版。 使用教程 使用方式有以下几种会慢慢讲到&#xff1a; heatmapDT(Year,T,V)heatmapDT(Year,T,V,MonLim)h…

数据结构|链表

概念&#xff1a;链表是一种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。单链表的形式就像一条铁链环环相扣它与顺序表最大的不同是&#xff0c;单链表的数据存储是在不连续的空间&#xff0c;存储的数据里面含有…

Stable Diffusion WebUI本地部署中遇到的一些错误

进来AI绘画大火&#xff0c;我便尝试在本地部署一下&#xff0c;电脑是M1的MacBook&#xff0c;不过windows应该也差不多。 参考官网的方法一步步安装&#xff0c;虽然最后成功了&#xff0c;但中途还是有不少问题。 首先安装homebrew&#xff0c;由于我早就已经安装好了&#…

前端项目上线后,浏览器缓存未刷新问题

文章目录问题背景一、解决办法二、实现原理关于缓存强缓存协商缓存刷新页面对浏览器的影响总结问题背景 前端页面开发测试完&#xff0c;要进行上线&#xff0c;某些页面上传更新到服务器之后&#xff0c;浏览器并没有更新&#xff0c;渲染的还是老页面。这是因为浏览器读了缓存…

es6 new Promise

Promise 是一个构造函数&#xff0c;本身身上有 all、reject、resolve 这几个方法&#xff0c;原型上有 then、catch 等方法。所以 Promise new 出来的对象确定就有 then、catch 方法。Promise 的构造函数接收一个参数&#xff0c;是函数&#xff0c;而且传入两个参数&#xff…

基于神经网络的自监督学习方法音频分离器(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 神经网络的输入是混合&#xff08;男性女性&#xff09;音频的振幅谱。神经网络的输出目标是男性说话者理想的软掩模。损失函数…

七,iperf3源代码分析:状态机及状态转换过程--->运行正向TCP单向测试时的服务端代码

本文目录一、测试用命令二、iperf3状态机中各个状态解析三、iperf3状态机迁移分析K-初始化测试对象&#xff08;NA--->初始化状态&#xff09;:A-服务器端测试对象开始运行&#xff08;初始化状态--->IPERF_START状态&#xff09;:B-建立控制连接&#xff08;初始化状态-…

论文公式符号规范

参考自1&#xff0c;记录论文公式的符号规范&#xff1a; 1.变量和公式符号表达 物理量 物理量符号用英文斜体字母或希腊斜体字母&#xff0c;表示物理量大小用数字加单位&#xff0c;单位使用正体。 例如&#xff1a; m10.05gx10.12ζ35.36mVm10.05 \mathrm{~g} \quad x10…

elasticsearch高级篇:核心概念和实现原理

1.elasticsearch核心概念1.1 索引(index)一个索引就是一个拥有几分相似特征的文档的集合。比如说&#xff0c;你可以有一个客户数据的索引&#xff0c;另一个产品目录的索引&#xff0c;还有一个订单数据的索引。一个索引由一个名字来标识&#xff08;必须全部是小写字母&#…

分布式数据库稳定性资料整理

这篇文章所讲的事情 初探分布式数据库这种有状态服务是如何保证系统的高可用的&#xff0c;可能会有勘误&#xff0c;欢迎指导。 正文 分布式数据库在说高可用的时候&#xff0c;主要是在讲宕机和网络分区时&#xff0c;系统的高可用如何保证&#xff0c;这点和我们在线上应…

【页面无响应】Web页面经常无响应前端如何定位与优化(已解決)

【写在前面】客户现场应用我们的系统时候&#xff0c;发现用着用着就出现1个页面无响应现象&#xff0c;给客户带来极其不好的体验&#xff0c;尤其是当重要工作汇报演示时&#xff0c;就给我看无响应&#xff0c;浏览器崩溃&#xff1f;这样对产品的发展无疑是致命的伤&#x…

水库大坝安全监测的主要坝体类型介绍

水电站和水库大坝安全的分类中有重力坝、土石坝等不同的大坝形式。就在这里详细水库大坝安全监测按照建造形式&#xff0c;基本上可以分为三类&#xff1a;重力坝、土石坝和拱坝。 &#xff08;1&#xff09;重力坝 重力坝&#xff0c;顾名思义就是利用自身重力来维持坝体稳定…