P2572 [SCOI2010]序列操作

P2572 [SCOI2010]序列操作

题意:

一个长度为n的01序列,下标从0开始,现在有五种变换操作和询问操作:

  1. 0 l r 把[l,r]区间内的所有数全变成0
  2. 1 l r 把[l,r]区间内的所有数全变成1
  3. 2 l r把[l,]区间内所有数全部取反
  4. 3 l r询问[l,r]区间内总共有多少个1
  5. 4 l r询问[l,r]区间内最多有多少连续的1

题解:

参考题解
很明显,裸的线段树,但是很难写。。
线段树要维护以下信息:

  1. sum:区间内1的个数
  2. maxx[0/1]区间内0/1最长连续子段
  3. lmax[0,1]包含区间左端点最长0/1子段
  4. rmax[0,1]包含区间右端点最长0/1子段

还有区间操作,所以还需要标记

  1. lazy=-1,0,1 .-1表示为无状态,0/1表示区间全部赋值为0/1
  2. rev=0,1,表示区间是否翻转

sum是维护区间内1的数量,maxx,lmax,rmax是用来维护区间内最长的01段(我们需要同时维护0段和1段,因为题目中存在反转操作)


需要维护的元素比较多,我们从pushup开始
区间和直接相加
然后维护0/1段
包含左端点的连续子段有两种情况:

  1. 当左区间全满/全空时,左端点可以跨越与右区间相连
  2. 直接继承左区间的lmax

右区间更新同理

对于区间最长子段,有三种情况:

  1. 直接继承左区间的较大值
  2. 直接继承右区间的较大值
  3. 左区间含右端点的最长子段+右区间含左端点的最长子段(即最长部分跨越区间分割线)

然后就是pushdown
线段树pushdown中,需要明确两个事:

  1. 标记的优先级
  2. 下放某个标记是否会对子节点的其他类型标记有所影响

在拆解一个标记时, 我们不仅需要明确将此标记下放到子节点, 同类型的标记应该如何改变, 而更应明确拆解此标记会对 不同类型的标记有何种影响

我们有两个标记,分别表示反转操作与重置操作。区间全体赋值优先级肯定高于翻转。如果先反转再重置,反转就没用了。所以当我们执行重置操作时,应该把反转标记清空。同时在下放标记时,应先下放重置标记,再下放反转标记,否则反转就会被重置覆盖。

在区间赋值标记拆解时,需要将子区间赋值标记更新为此值,并将子节点反转标记清空

在区间反转标记拆解时,需要分两种情况考虑此标记对子区间区间赋值翻转标记造成的影响。因为赋值标记优先级大于反转标记,所以有赋值标记时,直接区间赋值标记取反,其余情况翻转标记异或1


通过这个题会对线段树的lazy以及操作有更深的理解

代码:

// Problem: P2572 [SCOI2010]序列操作
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2572
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Data:2021-08-11 12:46:07
// By Jozky#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t staidTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
template <typename T> inline void read(T& x)
{T f= 1;x= 0;char ch= getchar();while (0 == isdigit(ch)) {if (ch == '-')f= -1;ch= getchar();}while (0 != isdigit(ch))x= (x << 1) + (x << 3) + ch - '0', ch= getchar();x*= f;
}
template <typename T> inline void write(T x)
{if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0');
}
void rd_test()
{
#ifdef ONLINE_JUDGE
#elsestaidTime= clock();freopen("in.txt", "r", stdin);
#endif
}
void Time_test()
{
#ifdef ONLINE_JUDGE
#elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - staidTime) / CLOCKS_PER_SEC);
#endif
}const int maxn= 3e5 + 9;
struct seg
{int l, r;int sum;int lazy;int rev;int maxx[2], lmax[2], rmax[2];
} tr[maxn << 2];
int a[maxn];
int n, m;
#define lid (id << 1)
#define rid (id << 1) | 1
void pushup(seg& ret, seg& L, seg& R)
{ret.sum= L.sum + R.sum;for (int i= 0; i <= 1; i++) {ret.lmax[i]= L.lmax[i];if (i == 1 && L.sum == L.r - L.l + 1) //左区间全满ret.lmax[i]+= R.lmax[i]; //可以跨越else if (i == 0 && L.sum == 0) //左区间全空,说明可以跨越到右区间ret.lmax[i]+= R.lmax[i];ret.rmax[i]= R.rmax[i];if (i == 1 && R.sum == R.r - R.l + 1) //如果右区间满,可以跨越到左区间ret.rmax[i]+= L.rmax[i];else if (i == 0 && R.sum == 0)ret.rmax[i]+= L.rmax[i];//左子树的右侧和右子树的左侧连接起来ret.maxx[i]= L.rmax[i] + R.lmax[i]; //中间//继承左子区间ret.maxx[i]= max(ret.maxx[i], L.maxx[i]); //继承子区间//继承右子区间ret.maxx[i]= max(ret.maxx[i], R.maxx[i]);}
}
void build(int id, int l, int r)
{tr[id].l= l;tr[id].r= r;tr[id].lazy= -1; //无状态if (l == r) {tr[id].sum= a[l];tr[id].maxx[0]= tr[id].lmax[0]= tr[id].rmax[0]= (a[l] == 0);tr[id].maxx[1]= tr[id].lmax[1]= tr[id].rmax[1]= (a[l] == 1);return;}int mid= (l + r) >> 1;build(lid, l, mid);build(rid, mid + 1, r);pushup(tr[id], tr[lid], tr[rid]);
}
void solve(int id, int val)
{tr[id].sum= (tr[id].r - tr[id].l + 1) * val;tr[id].lazy= val;tr[id].rev= 0;tr[id].maxx[val]= tr[id].lmax[val]= tr[id].rmax[val]= (tr[id].r - tr[id].l + 1);tr[id].maxx[val ^ 1]= tr[id].lmax[val ^ 1]= tr[id].rmax[val ^ 1]= 0;
}
void solve2(int id)
{//因为反转,所以取剩余部分tr[id].sum= (tr[id].r - tr[id].l + 1) - tr[id].sum;//总和考虑优先级,对其他标记的影响if (tr[id].lazy != -1)tr[id].lazy^= 1;elsetr[id].rev^= 1;//因为反转,所以区间0/1子段情况也要反转swap(tr[id].maxx[0], tr[id].maxx[1]);swap(tr[id].lmax[0], tr[id].lmax[1]);swap(tr[id].rmax[0], tr[id].rmax[1]);
}
void pushdown(int id)
{if (tr[id].lazy != -1) {tr[id].rev= 0; //清空反转标记solve(lid, tr[id].lazy);solve(rid, tr[id].lazy);tr[id].lazy= -1;}if (tr[id].rev) {solve2(lid);solve2(rid);tr[id].rev= 0;}
}
void update(int id, int val, int l, int r)
{if (tr[id].l == l && tr[id].r == r) {if (val == 0 || val == 1) {solve(id, val);}else if (val == 2) {solve2(id);}return;}pushdown(id);int mid= (tr[id].l + tr[id].r) >> 1;if (mid < l)update(rid, val, l, r);else if (mid >= r)update(lid, val, l, r);elseupdate(lid, val, l, mid), update(rid, val, mid + 1, r);pushup(tr[id], tr[lid], tr[rid]);
}
int query(int id, int l, int r)
{if (tr[id].l == l && tr[id].r == r)return tr[id].sum;pushdown(id);int mid= (tr[id].l + tr[id].r) >> 1;if (mid < l)return query(rid, l, r);else if (mid >= r)return query(lid, l, r);elsereturn query(lid, l, mid) + query(rid, mid + 1, r);
}
seg Q_max(int id, int l, int r)
{if (tr[id].l == l && tr[id].r == r)return tr[id];pushdown(id);int mid= (tr[id].l + tr[id].r) >> 1;if (mid < l)return Q_max(rid, l, r);else if (mid >= r)return Q_max(lid, l, r);else {seg ret;seg L= Q_max(lid, l, mid), R= Q_max(rid, mid + 1, r);pushup(ret, L, R);return ret;}
}
int main()
{//rd_test();read(n), read(m);for (int i= 1; i <= n; i++)read(a[i]);build(1, 1, n);while (m--) {int op, l, r;read(op), read(l), read(r);l++, r++;if (op == 0)update(1, 0, l, r); //区间全变成0else if (op == 1)update(1, 1, l, r); //区间全变成1else if (op == 2)update(1, 2, l, r); //区间全部取反else if (op == 3)printf("%d\n", query(1, l, r)); //询问区间内有多少个1else if (op == 4)printf("%d\n", Q_max(1, l, r).maxx[1]); //区间内有多少个连续的1}//Time_test();return 0;
}

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

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

相关文章

为您的机器配置开发环境

软件准备在本期视频中&#xff0c;我们将安装所序言的软件&#xff0c;并为我们的电脑配置.NET Core开发环境。我们需要安装如下2个软件&#xff1a;一个编辑器.NET Core SDK&#xff08;Software Development Kit&#xff09;下载并安装.NET Core 开发编辑器我的是Windows操作…

[CQOI2012] 局部极小值(状压DP + 容斥 + 搜索)

problem luogu-P3160 solution 这么小的数据范围&#xff0c;非暴力不状压。暴力 O(28!)O(28!)O(28!) 呵呵呵可以拉走了。 我们不妨从小到大填数字&#xff0c;这样如果局部极小值点还没有填的话&#xff0c;周围的九宫格就一定不能被填。 设 dp(s,i):dp(s,i):dp(s,i): 局…

基于Kubernetes 构建.NET Core 的技术体系

很多公司技术支持岗位的工作&#xff0c;如配置域名&#xff0c;部署环境&#xff0c;修改复位配置&#xff0c;服务重启&#xff0c;扩容缩容&#xff0c;梳理和完善监控&#xff0c;根据开发的需要查找日志等工作&#xff0c;需要和开发进行大量的沟通&#xff0c;如什么是外…

P4062 [Code+#1]Yazid 的新生舞会(分治做法)

P4062 [Code#1]Yazid 的新生舞会 题意&#xff1a; 给出一个序列&#xff0c;求有多少个子区间满足众数的出现次数大于区间长度的一半。 出现次数大于区间长度的一般我们称之为绝对众数 题解&#xff1a; 分治做法 对于一个区间[l,r]&#xff0c;设mid⌊lr2⌋\lfloor \frac…

[CQOI2014] 危桥(网络流)

problem luogu-P3163 solution 这是一道网络流好题&#xff0c;看的着摸不着吃不着。 初读完题&#xff0c;就知道这是一道“脱光了”的最大流。 建图基础版本&#xff1a; 建立额外源汇点。 无向边相同于两条有向边&#xff0c;直接建不影响&#xff0c;危桥流量设成 22…

那些优秀的开发者----汪宇杰:从重视细节,到成就技术专家

汪宇杰&#xff08;Edi Wang&#xff09;&#xff0c;.NET及Windows开发者&#xff0c;2018-2019年度微软最有价值专家&#xff08;Windows Development方向&#xff09;。现担任某金融科技企业的网站开发工程师。他对微软技术有鉴定的信念和不灭的热情&#xff0c;曾在Windows…

P4062 [Code+#1]Yazid 的新生舞会(线段树做法)

P4062 [Code#1]Yazid 的新生舞会&#xff08;线段树做法&#xff09; 题意&#xff1a; 给你一个序列a[1…n]​&#xff0c;求存在绝对众数的子区间个数。 绝对众数指&#xff1a;区间中出现次数最多的那个数&#xff0c;出现次数严格大于区间长度的一半。 题解&#xff1a…

《从零开始学ASP.NET CORE MVC》课程介绍

大家好&#xff0c;欢迎来到52ABP学院&#xff0c;收看我们的 《从零开始学ASP.NET CORE MVC》。ASP.NET Core 简介从2015年开始随时互联网成长&#xff0c;云计算和AI、大数据的爆发&#xff0c;大家从谈论项目信息化到数字化的转型&#xff0c;从ToC产业到ToB产业的转型&…

[ZJOI2015] 地震后的幻想乡(状压dp + 期望)

problem luogu-P3343 solution dp(i):dp(i):dp(i): 当恰好加入第 iii 小边时候&#xff0c;所有点联通的方案数。 则 ans∑idpi(mi)im1ans\sum_i \frac{dp_i}{\binom mi}\frac{i}{m1}ans∑i​(im​)dpi​​m1i​ 。 重点是如何计算出 dp(i)dp(i)dp(i)。 这个恰好的限制不好…

P2152 [SDOI2009]SuperGCD

P2152 [SDOI2009]SuperGCD 题意&#xff1a; 求a和b的最大公约数 a,b<101000010^{10000}1010000 题解&#xff1a; 高精度&#xff0c;java高精度直接有模板&#xff0c;c高精度结合gcd的辗转相减法 对于&#xff1a;a,b的gcd(a,b)有&#xff1a; 若a为奇数&#xff0c…

Docker - 容器部署 Consul 集群

目录 准备 Consul 镜像安装单个 Consul组装集群 Consul启动 Consul 和 Web 管理器Consul 命令简单介绍Web 管理器Server 加入集群Client 加入集群了解 ConsulConsul 使用场景Consul 优势Consul 中的概念说明简介安装总结引用和附件说明本文主要介绍怎么使用 Docker 在 Linux…

[LOJ3153] 三级跳(单调栈 + 线段树)

problem loj3153 solution 有一个显然正确但又不起眼却是正解必备的结论&#xff1a; 考虑 (x,y,z)(x,y,z)(x,y,z) 答案三元对&#xff0c;如果有一个数 i∈(x,y)∧ai≥axi\in(x,y)\wedge a_i\ge a_xi∈(x,y)∧ai​≥ax​&#xff0c;那么 (i,y,z)(i,y,z)(i,y,z) 一定是不劣…

P2167 [SDOI2009]Bill的挑战

P2167 [SDOI2009]Bill的挑战 题意&#xff1a; 有n个长度一样的字符串&#xff0c;字符串的每一位是&#xff1f;或者确定的字母&#xff0c;&#xff0c;求与这 N 个串中的刚好 K 个串匹配的字符串 T 的个数 1<N<15,1<|S|<50 题解&#xff1a; 很明显状态dp 我…

VS2017创建ASP.NET Core Web程序

创建ASP.NET Core Web应用程序如果您使用的是VS2019 请看 VS2019创建ASP.NET Core Web程序在这个视频中我们将讨论可用的不同项目模板及其功能预制的项目模板有什么不同&#xff0c;哪些是可以使用的&#xff0c;以及他们的作用。在Visual Studio2017中创建新的ASP.NET Core 项…

[ZJOI2015] 幻想乡战略游戏(树链剖分 + 线段树二分 + 带权重心)

problem luogu-P3345 solution 这是一个带权重心的题&#xff0c;考察动态点分治。点分治&#xff1f;呵&#xff0c;不可能的&#xff0c;这辈子都不可能写点分治 我们重新考虑重心的性质&#xff1a;以这个点为根时&#xff0c;所有子树的大小不会超过整体大小的一半。 …

巧用linux版powershell,管理linux下的docker

owershell,docker,cli,命令,docker ps,docker image第一章 在linux中搭建docker环境目的&#xff1a;在任意版本的linux&#xff08;物理机&#xff0c;虚拟机&#xff0c;节点机&#xff09;中&#xff0c;安装docker服务。动作&#xff1a;教程略&#xff0c;不是本文主要目的…

P1972 [SDOI2009]HH的项链

P1972 [SDOI2009]HH的项链 题意&#xff1a; 给你一个序列&#xff0c;问这个序列中的种类数 n,m,ai<1e6 题解&#xff1a; 三个方法&#xff1a;莫队(会超时)&#xff0c;树状数组&#xff0c;主席树(会超时) 莫队就是裸题&#xff0c;不讲了&#xff0c;复杂度O(n*sq…

从ASP.NET Core2.2到3.0你可能会遇到这些问题

趁着假期的时间所以想重新学习下微软的官方文档来巩固下基础知识。我们都知道微软目前已经发布了.NET Core3.0的第三个预览版&#xff0c;同时我家里的电脑也安装了vs2019。So&#xff0c;就用vs2019.NET Core3.0来跟着做一下Contoso University这个WEB应用&#xff0c;但是在基…

【学习笔记】整体二分

文章目录引整体二分几道模板题Dynamic Rankings[ZJOI2013]K大数查询[国家集训队]矩阵乘法[THUPC2017] 天天爱射击[CTSC2018]混合果汁引 例1. 给定 nnn 个数 aia_iai​&#xff0c;一次询问&#xff0c;询问区间 [l,r][l,r][l,r] 中的第 kkk 小数。 我们通常想到二分答案&#x…

P2157 [SDOI2009]学校食堂

P2157 [SDOI2009]学校食堂 题意&#xff1a; 小F 的学校在城市的一个偏僻角落&#xff0c;所有学生都只好在学校吃饭。学校有一个食堂&#xff0c;虽然简陋&#xff0c;但食堂大厨总能做出让同学们满意的菜肴。当然&#xff0c;不同的人口味也不一定相同&#xff0c;但每个人…