1858: [Scoi2010]序列操作

Time Limit: 10 Sec  Memory Limit: 64 MB

线段树,对于每个区间需要分别维护左右和中间的1和0连续个数,并在op=4时特殊处理一下。

Description

lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作:
   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。
对于每一种询问操作,lxhgww都需要给出回答,聪明的程序员们,你们能帮助他吗?

Input

输入数据第一行包括2个数,n和m,分别表示序列的长度和操作数目 第二行包括n个数,表示序列的初始状态 接下来m行,每行3个数,op, a, b,(0<=op<=4,0<=a<=b<n)表示对于区间[a, b]执行标号为op的操作。

Output

对于每一个询问操作,输出一行,包括1个数,表示其对应的答案

Sample Input

10 10
0 0 0 1 1 0 1 0 1 1
1 0 2
3 0 5
2 2 2
4 0 4
0 3 6
2 3 7
4 2 8
1 0 5
0 5 6
3 3 9

Sample Output

5
2
6
5

HINT

对于30%的数据,1<=n, m<=1000
对于100%的数据,1<=n, m<=100000

Source

#include<cstdio>
#define M 100010
inline int max(int a,int b){return a>b?a:b;}
struct tree{int l,r,s,lazy,sum,ml1,mr1,mm1,ml0,mr0,mm0;}tr[M*];
int a[M],n,m,x,y,v,op;
inline int read()
{
int tmp=;
char ch=getchar();
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<=''){tmp=tmp*+ch-'';ch=getchar();}
return tmp;
}
inline void pu(int p)
{
int p1=p<<,p2=p<<|;
tr[p].sum=tr[p1].sum+tr[p2].sum;
tr[p].mm1=tr[p1].mr1+tr[p2].ml1;
tr[p].mm0=tr[p1].mr0+tr[p2].ml0;
if(tr[p1].mr1==tr[p1].s) tr[p].ml1=tr[p1].mr1+tr[p2].ml1;
else tr[p].ml1=tr[p1].ml1;
if(tr[p1].mr0==tr[p1].s) tr[p].ml0=tr[p1].mr0+tr[p2].ml0;
else tr[p].ml0=tr[p1].ml0;
if(tr[p2].mr1==tr[p2].s) tr[p].mr1=tr[p2].mr1+tr[p1].mr1;
else tr[p].mr1=tr[p2].mr1;
if(tr[p2].mr0==tr[p2].s) tr[p].mr0=tr[p2].mr0+tr[p1].mr0;
else tr[p].mr0=tr[p2].mr0;
tr[p].mm1=max(tr[p].mm1,max(tr[p1].mm1,tr[p2].mm1));
tr[p].mm0=max(tr[p].mm0,max(tr[p1].mm0,tr[p2].mm0));
}
inline void change(int p)
{
int t1=tr[p].ml0,t2=tr[p].mr0,t3=tr[p].mm0;
tr[p].ml0=tr[p].ml1;
tr[p].ml1=t1;
tr[p].mr0=tr[p].mr1;
tr[p].mr1=t2;
tr[p].mm0=tr[p].mm1;
tr[p].mm1=t3;
}
inline void make(int l,int r,int p)
{
tr[p].l=l,tr[p].r=r,tr[p].s=tr[p].r-tr[p].l+,tr[p].lazy=-;
if(l==r)
{
tr[p].sum=a[l];
tr[p].ml1=tr[p].mm1=tr[p].mr1=a[l];
tr[p].ml0=tr[p].mm0=tr[p].mr0=a[l]^;
return;
}
int mid=(l+r)>>;
make(l,mid,p<<);
make(mid+,r,p<<|);
pu(p);
}
inline void pd(int p)
{
int lz=tr[p].lazy,p1=p<<,p2=p<<|;
if(lz==)
{
tr[p1].lazy=tr[p2].lazy=;
tr[p1].sum=;
tr[p2].sum=;
tr[p1].ml1=tr[p1].mr1=tr[p1].mm1=;
tr[p2].ml1=tr[p2].mr1=tr[p2].mm1=;
tr[p1].ml0=tr[p1].mr0=tr[p1].mm0=tr[p1].s;
tr[p2].ml0=tr[p2].mr0=tr[p2].mm0=tr[p2].s;
}
else if(lz==)
{
tr[p1].lazy=tr[p2].lazy=;
tr[p1].sum=tr[p1].s;
tr[p2].sum=tr[p2].s;
tr[p1].ml1=tr[p1].mr1=tr[p1].mm1=tr[p1].s;
tr[p2].ml1=tr[p2].mr1=tr[p2].mm1=tr[p2].s;
tr[p1].ml0=tr[p1].mr0=tr[p1].mm0=;
tr[p2].ml0=tr[p2].mr0=tr[p2].mm0=;
}
else if(lz==)
{
if(tr[p1].lazy==) tr[p1].lazy=;
else if(tr[p1].lazy==) tr[p1].lazy=;
else if(tr[p1].lazy==) tr[p1].lazy=-;
else tr[p1].lazy=;
if(tr[p2].lazy==) tr[p2].lazy=;
else if(tr[p2].lazy==) tr[p2].lazy=;
else if(tr[p2].lazy==) tr[p2].lazy=-;
else tr[p2].lazy=;
tr[p1].sum=tr[p1].s-tr[p1].sum;
tr[p2].sum=tr[p2].s-tr[p2].sum;
change(p1);change(p2);
}
tr[p].lazy=-;
}
inline int find1(int l,int r,int p)
{
pd(p);
if(tr[p].l==l&&tr[p].r==r) return tr[p].sum;
int mid=(tr[p].l+tr[p].r)>>;
if(mid>=r) return find1(l,r,p<<);
else if(mid<l) return find1(l,r,p<<|);
else return find1(l,mid,p<<)+find1(mid+,r,p<<|);
}
inline int findl(int l,int r,int p)
{
pd(p);
if(tr[p].ml1+l>r) return r-l+;
else return tr[p].ml1;
}
inline int findr(int l,int r,int p)
{
pd(p);
if(l+tr[p].mr1>r) return r-l+;
else return tr[p].mr1;
}
inline int find2(int l,int r,int p)
{
pd(p);
if(tr[p].l==l&&tr[p].r==r) return max(tr[p].ml1,max(tr[p].mm1,tr[p].mr1));
int mid=(tr[p].l+tr[p].r)>>;
if(mid>=r) return find2(l,r,p<<);
else if(mid<l) return find2(l,r,p<<|);
else return max(max(find2(l,mid,p<<),find2(mid+,r,p<<|)),findl(mid+,r,p<<|)+findr(l,mid,p<<));
}
inline void xg(int l,int r,int c,int p)
{
pd(p);
if(tr[p].l==l&&tr[p].r==r)
{
tr[p].lazy=c;
if(c==)
{
tr[p].ml1=tr[p].mr1=tr[p].mm1=;
tr[p].ml0=tr[p].mr0=tr[p].mm0=tr[p].s;
tr[p].sum=;
}
else if(c==)
{
tr[p].ml0=tr[p].mr0=tr[p].mm0=;
tr[p].ml1=tr[p].mr1=tr[p].mm1=tr[p].s;
tr[p].sum=tr[p].s;
}
else
{
tr[p].sum=tr[p].s-tr[p].sum;
change(p);
}
return;
}
int mid=(tr[p].l+tr[p].r)>>;
if(mid>=r) xg(l,r,c,p<<);
else if(mid<l) xg(l,r,c,p<<|);
else
{
xg(l,mid,c,p<<);
xg(mid+,r,c,p<<|);
}
pu(p);
}
int main()
{
n=read(),m=read();
for(int i=;i<=n;i++) a[i]=read();
make(,n,);
for(int i=;i<m;i++)
{
op=read();x=read();y=read();
if(op<) xg(x+,y+,op,);
else if(op==) printf("%d\n",find1(x+,y+,));
else printf("%d\n",find2(x+,y+,));
}
return ;
}

bzoj 1858: [Scoi2010]序列操作的更多相关文章

  1. (WAWAWAWAWAWA) BZOJ 1858: [Scoi2010]序列操作

    二次联通门 : BZOJ 1858: [Scoi2010]序列操作 /* BZOJ 1858: [Scoi2010]序列操作 已经... 没有什么好怕的的了... 16K的代码... 调个MMP啊.. ...

  2. BZOJ 1858: [Scoi2010]序列操作( 线段树 )

    略恶心的线段树...不过只要弄清楚了AC应该不难.... ---------------------------------------------------------------- #inclu ...

  3. bzoj 1858: [Scoi2010]序列操作【线段树】

    合并中间那块的时候没取max--WAWAWA 在线段树上维护一堆东西,分别是len区间长度,sm区间内1的个数,ll0区间从左开始最长连续0,ml0区间中间最长连续0,rl0区间从右开始最长连续0,l ...

  4. bzoj 1858: [Scoi2010]序列操作 || 洛谷 P2572

    记一下:线段树占空间是$2^{ceil(log2(n))+1}$ 这个就是一个线段树区间操作题,各种标记的设置.转移都很明确,只要熟悉这类题应该说是没有什么难度的. 由于对某区间set之后该区间原先待 ...

  5. 1858: [Scoi2010]序列操作

    1858: [Scoi2010]序列操作 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 3397 Solved: 1624 [Submit][Statu ...

  6. bzoj1858[Scoi2010]序列操作 线段树

    1858: [Scoi2010]序列操作 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 3079  Solved: 1475[Submit][Statu ...

  7. BZOJ_1858_[Scoi2010]序列操作_线段树

    BZOJ_1858_[Scoi2010]序列操作_线段树 Description lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询 ...

  8. 【题解】Luogu P2572 [SCOI2010]序列操作

    原题传送门:P2572 [SCOI2010]序列操作 这题好弱智啊 裸的珂朵莉树 前置芝士:珂朵莉树 窝博客里对珂朵莉树的介绍 没什么好说的自己看看吧 操作1:把区间内所有数推平成0,珂朵莉树基本操作 ...

  9. P2572 [SCOI2010]序列操作

    对自己 & \(RNG\) : 骄兵必败 \(lpl\)加油! P2572 [SCOI2010]序列操作 题目描述 lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要 ...

随机推荐

  1. VS2010无法修改资源文件

    最近,因为公司开发的需要,对开发环境进行全面的升级,在这其中也遇到了不少问题,在之后将陆续整理出来,以便以后查看. 之前开发环境:VS2008,ArcGIS9.3,ArcEngine9.3,Oracl ...

  2. 【随笔】ARP和RARP

    ARP协议是什么? ARP协议是"Address Resolution Protocol"(地址解析协议)的缩写.在局域网中,网络中实际传输的是"帧",帧里面是 ...

  3. XE3随笔11:Merge、Clone、ForcePath

    unit Unit1; interface uses   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, For ...

  4. MongoDB数据库简介及安装

    一.MongoDB数据库简介 简介 MongoDB是一个高性能,开源,无模式的,基于分布式文件存储的文档型数据库,由C++语言编写,其名称来源取自"humongous",是一种开源 ...

  5. 简单介绍智能DNS解析+双线路接入

    导读:在讨论这个问题,其中群友老孤同志也提供了不少非常有参考价值的资料,所以我们再把这些资料再整理一次,从比较底层的技术原理上重新进行一次分析.   我们知道,因为南电信北网通现象的存在,我们的服务器 ...

  6. 搭载hexo+github博客系统

    一.安装 Node.js 在官网 http://nodejs.org/ 下载winwos版本,点击安装完成即可. 二.git环境安装 对于git的安装,网上已经大量资料,就不赘述了. 三.安装 hex ...

  7. toString的理解

    Super的作用: 1. super可以直接调用父类的属性和方法. 2. super可以在子类的构造器中调用父类的构造器. 我们知道:实例化一个对象时,会调用构造器. 我们发现,仅仅实例化的是Stud ...

  8. (2016春) 作业1:博客和Github简单练习

    0. 博客和Github简单练习 总分:10分 1. 目的 博客使用:注册.发布博客.博客管理练习 Github使用:注册.文件同步等练习 2. 要求 (总体作业要求参考[链接]) 发布一篇博客: 介 ...

  9. git -- 如何解决冲突

    遇到冲突,首先要编辑冲突文件,可以使用vim或者其他工具,冲突文件变现为: <<<<HEAD 到 ==== :代表本地分支的修改内容 ==== 到 >>>&g ...

  10. Android性能优化方法(五)

    有时候,我们的页面中可能会包含一些布局,这些布局默认是隐藏的,当用户触发了一定的操作之后,隐藏的布局才会显示出来.比如,我们有一个Activity用来显示好友的列表,当用户点击Menu中的“导入”以后 ...