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. Tableview的更新和删除某一行

    .tableView的刷新 > 数据刷新的总体步骤 * 修改模型数据 * 刷新表格(刷新界面) > 刷新表格(刷新界面)的方法 * 全局刷新(每一行都会重新刷新) - (void)relo ...

  2. 转发(request.setRequestDispacter)和重定向(response.sendRedirect)的区别以及转发的include和forward的区别

    //response 重定向的时候,url是会跳转到新的页面的,输入的地址要包含项目名(可以跳到项目之外的页面,比如百度)//request 请求转发的时候,url是不会跳转到新页面的,输入的地址不包 ...

  3. 遇到的check the manual that corresponds to your MySQL server version for the right syntax错误

    遇到的check the manual that corresponds to your MySQL server version for the right syntax错误. 结果发现是SQL关键 ...

  4. 完美解决IE8有两个进程的问题

    完美解决IE8有两个进程的问题,照以下方法设置后就只有一个进程了,没有什么负影响哦! 方法: 1.win+R,在运行框里输入:gpedit.msc,回车进入组策略设置. 2.依次展开:计算机配置——管 ...

  5. <大学祭>

    我将20岁青涩的身影留在教室前的花坛边,远赴他乡,这些年过去了,他总是对我说别忘记我的梦: 我将那个沉静娇小的眼镜女孩印象留在第一排靠窗的座位,带着淡淡离愁而去,这些年过去了,她对我说,永恒的爱是心中 ...

  6. C# 基础(6)--Winform

    WinForm 简称,Windows Form ,调用.Net框架. Return 只是退出当前方法. MessageBox.Show("输入的Email地址是非法的!"); 把整 ...

  7. KMP算法(快速模式匹配)

    详细理解看这里:http://kb.cnblogs.com/page/176818/ 或者这里:http://blog.csdn.net/yutianzuijin/article/details/11 ...

  8. Windows中多个python版本共存的问题

    原创文章,未经本人允许进制转载. 在我的Windows中,先安装了python3.4,后来因为需要又安装了python2.7,结果发现: 直接双击1.py和命令行python 1.py使用的pytho ...

  9. 比较有价值的参考文档-----------------URL

    http://www.wendangku.net/doc/f7b4349108a1284ac85043bf.html             曙光服务器的IPMI http://noob.blog.1 ...

  10. java对xml文件做增删改查------摘录

    java对xml文件做增删改查 package com.wss; import java.io.File;import java.util.ArrayList;import java.util.Lis ...