Acwing: 一道关于线段树的好题(有助于全面理解线段树)
创始人
2024-05-30 07:26:16
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 ; 
}

相关内容

热门资讯

咱们班的淘气包小学作文(经典... 咱们班的淘气包小学作文 篇一咱们班的淘气包我班有一个淘气包,他叫小明。他是一个活泼好动的男孩,总是闯...
小学秋作文(精选6篇) 小学秋作文 篇一温暖的秋天秋天是一个美丽而温暖的季节。在秋天里,大自然的色彩变得丰富多彩,仿佛给大地...
冬季运动会优秀作文(最新6篇... 冬季运动会优秀作文 篇一冬季运动会中的快乐与收获冬季运动会是我们学校最受期待的盛事之一。今年,我有幸...
参观烈士陵园小学作文【精彩3... 参观烈士陵园小学作文 篇一今天,我们班级去参观了烈士陵园小学。这是一个位于城市郊区的学校,学校的名字...
一件新鲜事小学作文400字【... 一件新鲜事小学作文400字 篇一第一篇内容:捡到一只流浪猫今天放学后,我在回家的路上捡到了一只可爱的...
一年级小作文有哪些(精彩6篇... 一年级小作文有哪些 篇一在一年级的学习生活中,小朋友们开始接触到一些简单的写作训练,这些小作文既能帮...
绿荷叶,雨中晃小学作文【实用... 绿荷叶,雨中晃小学作文 篇一在小学的校园里,有一个独特的景色,那就是雨中的绿荷叶。每当雨水来临的时候...
惊喜小学作文(实用6篇) 惊喜小学作文 篇一:我最喜欢的礼物今天,我收到了一份惊喜礼物,让我非常开心和感动。这份礼物是我最喜欢...
小学生作文:在日本渔村的日子... 小学生作文:在日本渔村的日子 篇一在日本渔村的日子我有幸在上个寒假的时候,与父母一起去了日本的一个美...
游泳小健将作文600字【优秀... 游泳小健将作文600字 篇一游泳小健将是我们学校的一名优秀运动员,他是游泳队的一员,是个游泳小能手。...
爬网小学作文【精选3篇】 爬网小学作文 篇一我最喜欢的运动——爬网我是一名小学四年级的学生,我最喜欢的运动是爬网。每次看到高高...
欢声笑语的家作文【精彩3篇】 欢声笑语的家作文 篇一在我的家里,每天都充满着欢声笑语。家庭是一个温暖的港湾,是我们心灵的安乐之地。...
做笔筒小学生作文(精彩6篇) 做笔筒小学生作文 篇一我喜欢做笔筒我是一个小学生,每天都需要写很多的作业和笔记。为了方便整理我的文具...
我的小学启蒙老师作文(经典4... 我的小学启蒙老师作文 篇一我永远难以忘怀的启蒙老师还记得那个阳光明媚的早晨,当我第一次踏入小学校门的...
小燕子遇险记小学作文(实用3... 小燕子遇险记小学作文 篇一小燕子遇险记今天,我看到了一幅令人心碎的画面,那是一只小燕子遇到了巨大的困...
小学优秀作文【优选6篇】 小学优秀作文 篇一:我最喜欢的运动我最喜欢的运动是篮球。我对篮球的热爱始于我还是个小小孩的时候。每当...
写盼望的小学作文(实用6篇) 写盼望的小学作文 篇一盼望新学期的到来新学期即将开始,我感到无比的盼望和激动。我盼望着新的课程、新的...
立硬币小学作文(精简3篇) 立硬币小学作文 篇一我喜欢立硬币的游戏我是一个小学生,最近我发现了一个很有趣的游戏,那就是立硬币。这...
记忆里的歌小学作文(实用3篇... 记忆里的歌小学作文 篇一:童年的音符小时候,我家住在一个小村庄里,那里的生活简单而宁静。每天早晨,我...
在我的记忆深处小学生作文【经... 在我的记忆深处小学生作文 篇一快乐的操场时光记忆深处的小学时光,让我难以忘怀的便是在操场上的快乐时光...