1858: [Scoi2010]序列操作

Time Limit: 10 Sec Memory Limit: 64 MB

Submit: 3397 Solved: 1624

[Submit][Status][Discuss]

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)

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

解题思路

比较好的线段树题,对于操作0,1,2,我们可以打三个lazy标记。注意下放的时候应该先下放0,1标记,再下放翻转标记。而更新时如果是0,1标记,要将其他标记清空。

对于操作3我们可以维护一个sum数组表示区间内1的个数,直接输出即可。对于操作4,我的做法可能比较复杂,我维护了6个数组,分别是从左向右,从右向左,整个区间的最大0/1个数(不知道的跳转spoj GSS1),为什么要维护0,因为这样翻转操作直接swap即可,代码量较大,细节较多。

代码

#include<iostream>
#include<cstdio> using namespace std;
const int MAXN = 100005; inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
} int n,m,a[MAXN],L[MAXN<<2],R[MAXN<<2],lx0[MAXN<<2],rx0[MAXN<<2];
int lazy0[MAXN<<2],lazy1[MAXN<<2],rev[MAXN<<2],mx0[MAXN<<2];
int sum[MAXN<<2],lx1[MAXN<<2],mx1[MAXN<<2],rx1[MAXN<<2];
int ans,LX,RX,MX,SUM,LL,RR; inline void pushdown(int x){
if(lazy0[x]){
lazy0[x]=sum[x<<1]=sum[x<<1|1]=0;
lazy1[x<<1]=lazy1[x<<1|1]=0;
rev[x<<1]=rev[x<<1|1]=0;
lazy0[x<<1]=lazy0[x<<1|1]=1;
lx1[x<<1]=rx1[x<<1]=mx1[x<<1]=0;
lx1[x<<1|1]=rx1[x<<1|1]=mx1[x<<1|1]=0;
lx0[x<<1]=rx0[x<<1]=mx0[x<<1]=R[x<<1]-L[x<<1]+1;
lx0[x<<1|1]=rx0[x<<1|1]=mx0[x<<1|1]=R[x<<1|1]-L[x<<1|1]+1;
}
if(lazy1[x]){
lazy1[x]=rev[x<<1]=rev[x<<1|1]=0;
lazy0[x<<1]=lazy0[x<<1|1]=0;
lazy1[x<<1]=lazy1[x<<1|1]=1;
lx1[x<<1]=rx1[x<<1]=mx1[x<<1]=sum[x<<1]=R[x<<1]-L[x<<1]+1;
lx0[x<<1]=rx0[x<<1]=mx0[x<<1]=0;
lx1[x<<1|1]=rx1[x<<1|1]=mx1[x<<1|1]=sum[x<<1|1]=R[x<<1|1]-L[x<<1|1]+1;
lx0[x<<1|1]=rx0[x<<1|1]=mx0[x<<1|1]=0;
}
if(rev[x]){
rev[x]=0;rev[x<<1]^=1;rev[x<<1|1]^=1;
swap(lx1[x<<1],lx0[x<<1]);swap(rx1[x<<1],rx0[x<<1]);
swap(mx1[x<<1],mx0[x<<1]);swap(mx1[x<<1|1],mx0[x<<1|1]);
swap(lx1[x<<1|1],lx0[x<<1|1]);swap(rx1[x<<1|1],rx0[x<<1|1]);
sum[x<<1]=(R[x<<1]-L[x<<1]+1-sum[x<<1]);
sum[x<<1|1]=(R[x<<1|1]-L[x<<1|1]+1-sum[x<<1|1]);
}
} inline void pushup(int x){
sum[x]=sum[x<<1]+sum[x<<1|1];
L[x]=L[x<<1],R[x]=R[x<<1|1];
lx0[x]=lx0[x<<1];rx0[x]=rx0[x<<1|1];
if(sum[x<<1]==0)
lx0[x]=(R[x<<1]-L[x<<1]+1+lx0[x<<1|1]);
if(sum[x<<1|1]==0)
rx0[x]=(R[x<<1|1]-L[x<<1|1]+1+rx0[x<<1]);
mx0[x]=max(mx0[x<<1],max(mx0[x<<1|1],rx0[x<<1]+lx0[x<<1|1]));
lx1[x]=lx1[x<<1];rx1[x]=rx1[x<<1|1];
if(sum[x<<1]==(R[x<<1]-L[x<<1]+1))
lx1[x]=(R[x<<1]-L[x<<1]+1+lx1[x<<1|1]);
if(sum[x<<1|1]==(R[x<<1|1]-L[x<<1|1]+1))
rx1[x]=(R[x<<1|1]-L[x<<1|1]+1+rx1[x<<1]);
mx1[x]=max(mx1[x<<1],max(mx1[x<<1|1],rx1[x<<1]+lx1[x<<1|1])); } inline void build(int x,int l,int r){
if(l==r){
sum[x]=a[l];
L[x]=l;R[x]=r;
if(a[l]==0)
lx0[x]=rx0[x]=mx0[x]=1;
else
lx1[x]=rx1[x]=mx1[x]=1;
return;
}
int mid=l+r>>1;
build(x<<1,l,mid);build(x<<1|1,mid+1,r);
pushup(x);
} inline void update(int x,int l,int r,int ql,int qr,int k){
if(ql<=l && r<=qr){
int kk=k;
if(kk==2){
rev[x]^=1;
sum[x]=(r-l+1-sum[x]);
swap(lx0[x],lx1[x]);swap(rx0[x],rx1[x]);
swap(mx0[x],mx1[x]);
}
if(kk==0) {
rev[x]=sum[x]=lazy1[x]=0;lazy0[x]=1;
mx0[x]=lx0[x]=rx0[x]=r-l+1;
mx1[x]=lx1[x]=rx1[x]=0;
}
if(kk==1){
rev[x]=lazy0[x]=0;lazy1[x]=1;
mx0[x]=lx0[x]=rx0[x]=0;
mx1[x]=lx1[x]=rx1[x]=sum[x]=r-l+1;
}
return;
}
int mid=l+r>>1;
pushdown(x);
if(ql<=mid) update(x<<1,l,mid,ql,qr,k);
if(qr>mid) update(x<<1|1,mid+1,r,ql,qr,k);
pushup(x);
} inline int query1(int x,int l,int r,int ql,int qr){
if(ql<=l && r<=qr) return sum[x];
int mid=l+r>>1;
pushdown(x);
int ret=0;
if(ql<=mid) ret+=query1(x<<1,l,mid,ql,qr);
if(qr>mid) ret+=query1(x<<1|1,mid+1,r,ql,qr);
return ret;
} inline void merge(int x){
int A=LX,B=RX,C=MX,D=SUM;
SUM=D+sum[x];
if(D==RR-LL+1) LX=D+lx1[x];
RX=rx1[x];
if(sum[x]==R[x]-L[x]+1) RX=B+sum[x];
MX=max(C,max(mx1[x],B+lx1[x]));
ans=max(ans,MX);
if(!LL) LL=L[x];
RR=R[x];
} inline void query2(int x,int l,int r,int ql,int qr){
if(ql<=l && r<=qr) {merge(x);return;}
int mid=l+r>>1;
pushdown(x);
if(ql<=mid) query2(x<<1,l,mid,ql,qr);
if(qr>mid) query2(x<<1|1,mid+1,r,ql,qr);
} int main(){
n=rd();m=rd();
for(register int i=1;i<=n;i++) a[i]=rd();
build(1,1,n);
// for(register int i=1;i<=(n<<1);i++)
// cout<<L[i]<<" "<<R[i]<<" "<<sum[i]<<" "<<endl;
while(m--){
// cout<<sum[1]<<endl;
int op=rd(),ql=rd(),qr=rd();ql++;qr++;
if(op==0 || op==1 || op==2) update(1,1,n,ql,qr,op);
else if(op==3) printf("%d\n",query1(1,1,n,ql,qr));
else if(op==4) {query2(1,1,n,ql,qr);printf("%d\n",ans);ans=LX=RX=MX=SUM=LL=RR=0;}
}
return 0;
}

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

  1. bzoj 1858: [Scoi2010]序列操作

    1858: [Scoi2010]序列操作 Time Limit: 10 Sec  Memory Limit: 64 MB 线段树,对于每个区间需要分别维护左右和中间的1和0连续个数,并在op=4时特殊 ...

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

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

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

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

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

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

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

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

  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. 洛谷P3834【模板】可持久化线段树 1(主席树)

    题目背景 这是个非常经典的主席树入门题--静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输 ...

  2. 2019个人计划与Flag与期望

    突然发现写博客是真的好. 希望未来能在其他地方写上日记. 总结2018中的个人缺陷: 1.忘掉了学习方法或者说学习方法不正确 2.偶尔就会去偷下懒,对自己不够严格,自控能力差. 3.心态虽比以前好很多 ...

  3. 中国剩余定理模数不互质的情况(poj 2891

    中国剩余定理模数不互质的情况主要有一个ax+by==k*gcd(a,b),注意一下倍数情况和最小 https://vjudge.net/problem/POJ-2891 #include <io ...

  4. Vim操作 -- 按列

    1, 拷贝行 Y y 拷贝当前光标字符 如果需要拷贝整个单词,可以用 ye,e表示跳到词尾 2, 粘贴 P(大写) 粘贴到光标前 p(小写)粘贴到光标后 3, 进入快操作模式 ctrl+q 4, 用 ...

  5. HTML+css 小组件

    1.三角 代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <t ...

  6. 廖雪峰Java15JDBC编程-3JDBC接口-2JDBC查询

    我们可以使用JDBC查询来执行select语句. 1. Statement try(Connection conn = DriverManager.getConnection(JDBC_URL, JD ...

  7. Java 的 JJWT 实现 JWT

    JJWT是一个提供端到端的JWT创建和验证的Java库 依赖 <dependency> <groupId>io.jsonwebtoken</groupId> < ...

  8. Django实现简单的图书管理系统

    目录 Django写图书管理系统 功能截图 创建Django项目 开始项目 配置文件 建立路由关系 开始写Django项目 编写核心逻辑函数 写前端页面 add_author.html add_boo ...

  9. position:fixed失效问题

    fixed定位的元素,如果父级有transform样式,值不为none,那么fixed定位就会失效. 解决方法:使用transform样式的元素,不要包含fixed定位的子元素.

  10. IOS学习笔记57--IOS7状态栏适配(二)

    上一遍文章通过XIB的设置达到了状态栏和view重合的问题,这一篇我们讲一讲网传的修改window frame方法. 先上步骤: 第一:在appdeletage里面 添加如下代码:      if ( ...