BZOJ1858 [Scoi2010]序列操作
来源:互联网 发布:flyme解锁软件 编辑:程序博客网 时间:2024/05/17 06:29
BZOJ1858 [Scoi2010]序列操作
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 100 0 0 1 1 0 1 0 1 11 0 23 0 52 2 24 0 40 3 62 3 74 2 81 0 50 5 63 3 9
Sample Output
5265
HINT
对于30%的数据,1<=n, m<=1000 对于100%的数据,1< = n, m < = 100000
题解
因为有取反,所以我们要维护1的最长与0的最长与区间两端1/0的长度。这样,如果为取反操作的化就1/0互换。
还有一点要注意的是求答案的时候不仅要返回区间最长,也要返回区间两端1的长度。再合并区间求最长。
#include <cstdio>#include <iostream>#include <cmath>#include <stack>#include <algorithm>#include <cstring>#include <climits>#define MAXN 100000+10using namespace std;int n,m,l0[MAXN<<2],r0[MAXN<<2],m0[MAXN<<2];int l1[MAXN<<2],r1[MAXN<<2],m1[MAXN<<2],mark[MAXN<<2],rev[MAXN<<2],num[MAXN<<2];int L[MAXN<<2],R[MAXN<<2],a[MAXN];void pushup(int rt){ l1[rt]=l1[rt<<1];r1[rt]=r1[rt<<1|1]; l0[rt]=l0[rt<<1];r0[rt]=r0[rt<<1|1]; if(l1[rt]==R[rt<<1]-L[rt<<1]+1) l1[rt]+=l1[rt<<1|1]; if(r1[rt]==R[rt<<1|1]-L[rt<<1|1]+1) r1[rt]+=r1[rt<<1]; if(l0[rt]==R[rt<<1]-L[rt<<1]+1) l0[rt]+=l0[rt<<1|1]; if(r0[rt]==R[rt<<1|1]-L[rt<<1|1]+1) r0[rt]+=r0[rt<<1]; m1[rt]=max(max(m1[rt<<1],m1[rt<<1|1]),l1[rt<<1|1]+r1[rt<<1]); m0[rt]=max(max(m0[rt<<1],m0[rt<<1|1]),l0[rt<<1|1]+r0[rt<<1]); num[rt]=num[rt<<1]+num[rt<<1|1];}void pushdown(int rt,int l,int r){ if(mark[rt]!=-1||rev[rt]) { int m=(l+r)>>1; if(l==r) return ; else { if(mark[rt]!=-1) { mark[rt<<1]=mark[rt<<1|1]=mark[rt]; r1[rt<<1]=l1[rt<<1]=m1[rt<<1]=num[rt<<1]=mark[rt]*(m-l+1); r1[rt<<1|1]=l1[rt<<1|1]=m1[rt<<1|1]=num[rt<<1|1]=mark[rt]*(r-m); r0[rt<<1]=l0[rt<<1]=m0[rt<<1]=!mark[rt]*(m-l+1); r0[rt<<1|1]=l0[rt<<1|1]=m0[rt<<1|1]=!mark[rt]*(r-m); rev[rt<<1]=rev[rt<<1|1]=0; } if(rev[rt]==1) { num[rt<<1]=(m-l+1)-num[rt<<1]; num[rt<<1|1]=(r-m)-num[rt<<1|1]; swap(r1[rt<<1],r0[rt<<1]); swap(r1[rt<<1|1],r0[rt<<1|1]); swap(l1[rt<<1],l0[rt<<1]); swap(l1[rt<<1|1],l0[rt<<1|1]); swap(m1[rt<<1],m0[rt<<1]); swap(m1[rt<<1|1],m0[rt<<1|1]); rev[rt<<1]^=rev[rt]; rev[rt<<1|1]^=rev[rt]; } } rev[rt]=0;mark[rt]=-1; }}void build(int rt,int l,int r){ mark[rt]=-1;L[rt]=l;R[rt]=r; if(l==r) { l1[rt]=m1[rt]=r1[rt]=num[rt]=a[l]; l0[rt]=m0[rt]=r0[rt]=!a[l]; return ; } int m=(l+r)>>1; build(rt<<1,l,m); build(rt<<1|1,m+1,r); pushup(rt);}void update(int L,int R,int c,int l,int r,int rt){ pushdown(rt,l,r); if(L<=l&&r<=R) { if(c<2) { r1[rt]=l1[rt]=m1[rt]=num[rt]=c*(r-l+1); r0[rt]=l0[rt]=m0[rt]=(!c)*(r-l+1); mark[rt]=c; }else { swap(r1[rt],r0[rt]);swap(l1[rt],l0[rt]);swap(m1[rt],m0[rt]); num[rt]=(r-l+1)-num[rt]; rev[rt]^=1; } return ; } int m=(l+r)>>1; if(L<=m) update(L,R,c,l,m,rt<<1); if(R>m) update(L,R,c,m+1,r,rt<<1|1); pushup(rt);}int query(int L,int R,int v,int l,int r,int rt,int &ln,int &rn){ if(L<=l&&r<=R) { ln=l1[rt];rn=r1[rt]; return v?m1[rt]:num[rt]; } int m=(l+r)>>1,lans=0,rans=0,aans=0,ln1=0,rn1=0,ln2=0,rn2=0; pushdown(rt,l,r); if(L<=m) lans=query(L,R,v,l,m,rt<<1,ln1,rn1),aans+=rn1; if(R>m) rans=query(L,R,v,m+1,r,rt<<1|1,ln2,rn2),aans+=ln2; if(v) { ln=ln1;if(ln1==m-l+1) ln+=ln2; rn=rn2;if(rn2==r-m) rn+=rn1; return max(max(lans,rans),aans); } else return lans+rans;}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n); int x,b,c,t1,t2; for(int i=1;i<=m;i++) { scanf("%d%d%d",&x,&b,&c); b++,c++; if(x<=2) update(b,c,x,1,n,1); else if(x==3) printf("%d\n",query(b,c,0,1,n,1,t1,t2)); else if(x==4) printf("%d\n",query(b,c,1,1,n,1,t1,t2)); } return 0;}
0 0
- bzoj1858【scoi2010】序列操作
- [BZOJ1858] [Scoi2010]序列操作
- bzoj1858: [Scoi2010]序列操作
- BZOJ1858 [Scoi2010]序列操作
- BZOJ1858: [Scoi2010]序列操作
- BZOJ1858 [Scoi2010]序列操作
- bzoj1858: [Scoi2010]序列操作
- bzoj1858 [Scoi2010]序列操作
- 【BZOJ1858】[Scoi2010]序列操作 线段树
- [BZOJ1858]SCOI2010序列操作|线段树
- 【BZOJ1858】[Scoi2010]序列操作【线段树】
- 【BZOJ1858】序列操作(SCOI2010)-线段树
- [省选] [线段树] [BZOJ1858] [SCOI2010] 序列操作
- 线段树 BZOJ1858 [Scoi2010]序列操作
- 【bzoj1858】【Scoi2010】序列操作【位运算】【卡常大法好】
- 线段树——BZOJ1858/Luogu2572 [SCOI2010]序列操作
- hdu3397 Sequence operation 线段树区间更新&&bzoj1858: [Scoi2010]序列操作
- bzoj1858序列操作 线段树
- BZOJ1067 [SCOI2007]降雨量
- Mac系统eclipse配置python开发环境
- 使用MyEclipse修改web项目名称后无法访问
- Scala 官方文档 --包结构解读
- Error executing DDL via JDBC Statement
- BZOJ1858 [Scoi2010]序列操作
- Ubuntu 下chrome 安装
- linux修改只读文件
- Android开发实践:Java层与Jni层的数组传递
- Oracle execute immediate 拼接条件 参数化
- POJ2777 Count Color 线段树
- 算法导论 思考题 10-2
- 毕设第一步
- C++ STL源码分析之 list