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 标记的下放好 ...
随机推荐
- yum install 安装 下载好的rpm包 会并依赖包一起安装 zoom电话会议的安装
[root@ok-T Downloads]# rpm -ivh zoom_x86_64.rpm error: Failed dependencies: libxcb-image.so.()(64bit ...
- Hihicoder 题目1 : Trie树(字典树,经典题)
题目1 : Trie树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编 ...
- babyClock 1.0发布(Android2.2以上)
[总体说明] babyClock是以天为单位,进行提醒的小工具:可以设置多个闹钟,每个闹钟又按照频率分为多个提醒:过期后自动设置到明天该时刻进行提醒. 一个闹钟包含时间区段.提醒频率:进入时间区段时, ...
- C# 重绘tabControl,添加关闭按钮(续)
在上一篇随笔中,添加关闭按钮是可以实现 ,但细心一点就会发现,每次关闭一个选项卡,tableControl都会自动跳到第一个页面,显然 这不是我们想要的,为此,我修改了部分的代码.除此之外,我还添加了 ...
- php计算几分钟前、几小时前等
function format_date($time){ $t=time()-$time; $f=array( '=>'年', '=>'个月', '=>'星期', '=>'天' ...
- [SVN] SVN在Eclipse里的各个状态解释
中文意义: A代表添加D代表删除U代表更新C代表合并,并且合并中有冲突G代表合并,合并中没有冲突 每个字母代表的意义: U = item (U)pdated to repository version ...
- long和int的区别
转自:http://blog.sina.com.cn/s/blog_6f62c9510101svjz.html 突然间就想到了long和int到底什么区别(发现有很多问题都是突然间想到的),然后百度. ...
- FrameLayout
FrameLayout是最简单的布局了. ① 所有放在布局里的控件,都按照层次堆叠在屏幕的左上角.后加进来的控件覆盖前面的控件. ② 该布局container可以用来占有屏幕的某块区域来显示单一的对象
- 使用python做科学计算
这里总结一个guide,主要针对刚开始做数据挖掘和数据分析的同学 说道统计分析工具你一定想到像excel,spss,sas,matlab以及R语言.R语言是这里面比较火的,它的强项是强大的绘图功能以及 ...
- 处理FF margin-top下降问题
处理DIV子级ZImargin-top下降,父级更着下降问题 html结构如下 <div id="top"> <div id="zi"> ...