BZOJ1858[Scoi2010]序列操作 题解
题目大意:
有一个01序列,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0;1 a b 把[a, b]区间内的所有数全变成1;2 a b 把[a,b]区间内的所有数全部取反,也就是说把所有的0变成1,把所有的1变成0;3 a b 询问[a, b]区间内总共有多少个1;4 a b 询问[a, b]区间内最多有多少个连续的1。
思路:
维护每一段数的和、左端和右端以及整段中连续的0和1的长度,并使用标记进行下传。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#define N 400000
using namespace std; int root,num,cnt,lmax[][N],rmax[][N],mmax[][N],sum[N],tag[][N],rev[N],h[N],t[N],rc[N],lc[N],a[N]; void up_date(int x,int k)
{
int l=lc[x],r=rc[x];
lmax[k][x]=lmax[k][l],rmax[k][x]=rmax[k][r];
if (lmax[k][l]==t[l]-h[l]+) lmax[k][x]+=lmax[k][r];
if (rmax[k][r]==t[r]-h[r]+) rmax[k][x]+=rmax[k][l];
mmax[k][x]=max(max(mmax[k][l],mmax[k][r]),rmax[k][l]+lmax[k][r]);
} void build(int l,int r,int &cur)
{
cur=++num,tag[][cur]=tag[][cur]=rev[cur]=;
h[cur]=l,t[cur]=r;
if (l==r)
{
lc[cur]=rc[cur]=;
lmax[][cur]=rmax[][cur]=mmax[][cur]=(a[l]==);
lmax[][cur]=rmax[][cur]=sum[cur]=mmax[][cur]=(a[r]==);
return;
}
int mid=l+r>>;
build(l,mid,lc[cur]),build(mid+,r,rc[cur]);
up_date(cur,),up_date(cur,),sum[cur]=sum[lc[cur]]+sum[rc[cur]];
} void mark(int x,int k)
{
tag[k][x]=,tag[k^][x]=rev[x]=,sum[x]=(t[x]-h[x]+)*k;
lmax[k][x]=rmax[k][x]=mmax[k][x]=t[x]-h[x]+;
lmax[k^][x]=rmax[k^][x]=mmax[k^][x]=;
} void re(int x)
{
rev[x]^=,sum[x]=t[x]-h[x]+-sum[x];
swap(lmax[][x],lmax[][x]),swap(rmax[][x],rmax[][x]),swap(mmax[][x],mmax[][x]);
} void push_down(int x)
{
if (tag[][x]) mark(lc[x],),mark(rc[x],),tag[][x]=;
if (tag[][x]) mark(lc[x],),mark(rc[x],),tag[][x]=;
if (rev[x]) re(lc[x]),re(rc[x]),rev[x]=;
} void change(int l,int r,int cur,int k)
{
if (h[cur]>r || t[cur]<l) return;
if (h[cur]>=l && t[cur]<=r)
{
if (k<) mark(cur,k);
else re(cur);
return;
}
push_down(cur);
change(l,r,lc[cur],k),change(l,r,rc[cur],k);
up_date(cur,),up_date(cur,),sum[cur]=sum[lc[cur]]+sum[rc[cur]];
} int ask1(int l,int r,int cur)
{
if (h[cur]>r || t[cur]<l) return ;
if (h[cur]>=l && t[cur]<=r) return sum[cur];
push_down(cur);
return ask1(l,r,lc[cur])+ask1(l,r,rc[cur]);
} int ask2(int l,int r,int cur)
{
if (l==h[cur] && r==t[cur]) return cur;
int mid=h[cur]+t[cur]>>;
push_down(cur);
if (r<=mid) return ask2(l,r,lc[cur]);
else if (l>mid) return ask2(l,r,rc[cur]);
else
{
int ans=++cnt;
lc[ans]=ask2(l,mid,lc[cur]),rc[ans]=ask2(mid+,r,rc[cur]);
up_date(ans,),up_date(ans,),sum[ans]=sum[lc[ans]]+sum[rc[ans]];
return ans;
}
} int main()
{
int n,m,i,x,y,z;
scanf("%d%d",&n,&m);
for (i=;i<=n;i++) scanf("%d",&a[i]);
build(,n,root);
for (i=;i<=m;i++)
{
scanf("%d%d%d",&z,&x,&y);
x++,y++;
if (z==) printf("%d\n",ask1(x,y,root));
else if (z==) cnt=num,printf("%d\n",mmax[][ask2(x,y,root)]);
else change(x,y,root,z);
}
return ;
}
BZOJ1858[Scoi2010]序列操作 题解的更多相关文章
- bzoj1858[Scoi2010]序列操作 线段树
1858: [Scoi2010]序列操作 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 3079 Solved: 1475[Submit][Statu ...
- BZOJ1858 [Scoi2010]序列操作(线段树)
题目链接 [Scoi2010]序列操作 考验代码能力的一道好题. 思想还是很简单的(直接上线段树),但是比较难写. #include <bits/stdc++.h> using names ...
- BZOJ1858:[SCOI2010]序列操作——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=1858 lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于 ...
- [BZOJ1858] [SCOI2010] 序列操作 解题报告 (线段树)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1858 Description lxhgww最近收到了一个01序列,序列里面包含了n个数, ...
- 【分块】bzoj1858 [Scoi2010]序列操作
分块 Or 线段树 分块的登峰造极之题 每块维护8个值: 包括左端点在内的最长1段: 包括右端点在内的最长1段: 该块内的最长1段: 该块内1的个数: 包括左端点在内的最长0段://这四个是因为可能有 ...
- bzoj1858: [Scoi2010]序列操作
lazy-tag线段树. #include<cstdio> #include<algorithm> #include<cstring> using namespac ...
- bzoj千题计划177:bzoj1858: [Scoi2010]序列操作
http://www.lydsy.com/JudgeOnline/problem.php?id=1858 2018 自己写的第1题,一遍过 ^_^ 元旦快乐 #include<cstdio> ...
- [待码][BZOJ1858]SCOI2010序列操作 jzyzoj1655
待码的线段树.....太长了看上去不是很想写 [ 什么破理由啊摔,不要脸 ] 嗯先水几道再写
- bzoj1858 [Scoi2010]序列操作——线段树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1858 线段树...调了一个上午...(后面带 // 的都是改出来的) lazy 标记的下放好 ...
随机推荐
- Delphi面向对象---接口
从Delphi3开始支持接口.接口定义了能够与一个对象进行交互操作的一组过程和函数.对一个接口进行定义包含两个方面的内容: 1)一方面是实现这个接口 2)另一方面是定义接口的客户 一个类能够实现多个接 ...
- 【131031】<meta http-equiv=...> 的功能
1.定义语言 格式: 〈meta http-equiv=″Content-Type″ content=″text/html; charset=gb2312″〉 这是META最常见的用法,在制作网页时, ...
- gdb调试小结
gdb最基本的调试命令. 1以调试程序test.cpp为例: 进入调试环境 gdb test 2.b 12 在文件的第12行设置断点. 删除断点: info b 列出所有的断点信息 (gdb) inf ...
- linux下java环境配置
非常简单的三行命令就搞定了! $ sudo add-apt-repository ppa:webupd8team/java$ sudo apt-get update$ sudo apt-get ins ...
- 遍历注册表回调函数(仿PCHunter CmpBack)
遍历注册表回调函数(仿PCHunter CmpBack) typedef struct _CAPTURE_REGISTRY_MANAGER { PDEVICE_OBJECT deviceObject; ...
- html css js 一些记录.
webstorm 的基本使用 webstorm 格式化 html 代码: Ctrl+Alt+L js html css 基本使用 注意 dom 的 innerHTML会刷新dom,所以里面包含的事件绑 ...
- 大端模式 VS 小端模式
简单点说,就是字节的存储顺序,如果数据都是单字节的,那怎么存储无所谓了,但是对于多字节数据,比如int,double等,就要考虑存储的顺序了.注意字节序是硬件层面的东西,对于软件来说通常是透明的.再说 ...
- ffmpeg处理RTMP流媒体的命令 发送流媒体的命令(UDP,RTP,RTMP)
将文件当做直播送至live ffmpeg -re -i localFile.mp4 -c copy -f flv rtmp://server/live/streamName re限制输出速率,按照 ...
- 关于css的全面学习笔记
1.text-align 属性规定元素中的文本的水平对齐方式.该属性通过指定行框与哪个点对齐,从而设置块级元素内文本的水平对齐方式.通过允许用户代理调整行内容中字母和字之间的间隔,可以支持值 just ...
- hdu1150 匈牙利
http://acm.split.hdu.edu.cn/showproblem.php?pid=1150 题目大意:有两台机器A和B以及N个需要运行的任务.每台机器有M种不同的模式,而每个任务都恰好在 ...