Acwing: 一道关于线段树的好题(有助于全面理解线段树)
创始人
2024-05-30 05:22:33
0

题目链接🔗: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 
#include 
#include 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 ; 
}

相关内容

热门资讯

如果当初没有安卓系统,科技世界... 想象如果没有安卓系统,我们的生活会是怎样的呢?是不是觉得有点不可思议?别急,让我们一起穿越时空,探索...
安卓电视装win系统,系统转换... 亲爱的读者们,你是否曾想过,在你的安卓电视上装一个Windows系统,让它瞬间变身成为一台功能强大的...
安卓手机还原系统好处,重拾流畅... 你有没有遇到过安卓手机卡顿、运行缓慢的情况?别急,今天就来给你揭秘一下安卓手机还原系统的那些好处,让...
安卓系统能跑win吗,探索跨平... 你有没有想过,你的安卓手机里能不能装上Windows系统呢?这听起来是不是有点像科幻电影里的情节?别...
安卓车载系统蓝牙设置,畅享智能... 你有没有发现,现在开车的时候,手机和车载系统之间的互动越来越频繁了呢?这不,今天就来给你详细说说安卓...
奥利奥安卓系统,探索新一代智能... 你有没有想过,一块小小的奥利奥饼干竟然能和强大的安卓系统扯上关系?没错,今天就要来聊聊这个跨界组合,...
微信使用安卓系统,功能解析与操... 你有没有发现,现在用微信的人越来越多了呢?尤其是安卓系统的用户,简直就像潮水一样涌来。今天,就让我带...
体验最新原生安卓系统,极致体验... 你有没有想过,手机系统就像是我们生活的调味品,有时候换一种口味,生活都会变得有趣起来呢?最近,我体验...
安卓系统能玩原神,尽享奇幻冒险... 你有没有想过,在安卓系统上也能畅玩《原神》这样的热门游戏呢?没错,就是那个画面精美、角色丰富、玩法多...
安卓写手机银行系统,基于安卓平... 你有没有想过,手机银行系统在我们日常生活中扮演了多么重要的角色呢?每天刷刷手机,就能轻松管理账户,转...
僵尸之夜恐怖安卓系统,揭秘恐怖... 僵尸之夜,恐怖安卓系统来袭!想象一个寂静的夜晚,你正沉浸在美梦中,突然,一阵诡异的铃声打破了夜的宁静...
谷歌框架和安卓系统,构建智能移... 你有没有想过,为什么你的手机那么聪明,能帮你找到路线,还能帮你拍出美美的照片呢?这都要归功于一个超级...
安卓系统和oppo系统哪个流畅... 你有没有想过,手机系统哪个更流畅呢?安卓系统和OPPO系统,这两个名字听起来就让人心动。今天,咱们就...
安卓怎么用微软系统,利用微软系... 你是不是也和我一样,对安卓手机上的微软系统充满了好奇?想象那熟悉的Windows界面在你的安卓手机上...
安卓系统如何安装nfc,安卓系... 你有没有想过,用手机刷公交卡、支付账单,是不是比掏出钱包来得酷炫多了?这就得归功于NFC技术啦!今天...
ios系统可以转安卓,跨平台应... 你有没有想过,你的iPhone手机里的那些宝贝应用,能不能搬到安卓手机上继续使用呢?没错,今天就要来...
iOSapp移植到安卓系统,i... 你有没有想过,那些在iOS上让你爱不释手的app,是不是也能在安卓系统上大放异彩呢?今天,就让我带你...
现在安卓随便换系统,探索个性化... 你知道吗?现在安卓手机换系统简直就像换衣服一样简单!没错,就是那种随时随地、随心所欲的感觉。今天,就...
安卓系统安装按钮灰色,探究原因... 最近发现了一个让人头疼的小问题,那就是安卓手机的安装按钮突然变成了灰色,这可真是让人摸不着头脑。你知...
安卓7.1.1操作系统,系统特... 你知道吗?最近我在手机上发现了一个超级酷的新玩意儿——安卓7.1.1操作系统!这可不是什么小打小闹的...