首页 > 代码库 > 序列操作(bzoj 1858)
序列操作(bzoj 1858)
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的操作="" <="" div="">
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
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
2
6
5
HINT
对于30%的数据,1<=n, m<=1000
对于100%的数据,1<=n, m<=100000
/* 不想写线段树,写的分块。 维护一下每个块的左最大连续区间,右最大连续区间,最大连续区间,和几个标记(无/全0/全1/取反)。 */ #include<cstdio> #include<iostream> #include<cmath> #include<cstring> #define N 100010 #define M 510 using namespace std; int a[N],bl[N],n,m,size; int tag[M],lc0[M],rc0[M],sc0[M],lc1[M],rc1[M],sc1[M],sum[M]; void init(int i){ tag[i]=-1;lc0[i]=rc0[i]=sc0[i]=lc1[i]=rc1[i]=sc1[i]=sum[i]=0; for(int j=(i-1)*size+1;j<=min(n,i*size);j++) if(a[j]) sum[i]++; int fl=0,p=0; for(int j=(i-1)*size+1;j<=min(n,i*size);j++){ if(!a[j]&&!fl) lc0[i]++; else fl=1; if(!a[j]) p++;else p=0; sc0[i]=max(sc0[i],p); } fl=0; for(int j=min(n,i*size);j>(i-1)*size;j--){ if(!a[j]&&!fl) rc0[i]++; else fl=1; } fl=0,p=0; for(int j=(i-1)*size+1;j<=min(n,i*size);j++){ if(a[j]&&!fl) lc1[i]++; else fl=1; if(a[j]) p++;else p=0; sc1[i]=max(sc1[i],p); } fl=0; for(int j=min(n,i*size);j>(i-1)*size;j--){ if(a[j]&&!fl) rc1[i]++; else fl=1; } } void pushdown(int i){ if(tag[i]==-1) return; if(tag[i]==0||tag[i]==1) for(int j=(i-1)*size+1;j<=i*size;j++) a[j]=tag[i]; else for(int j=(i-1)*size+1;j<=i*size;j++) a[j]^=1; tag[i]=-1; } void change1(int x,int y,int v){ pushdown(bl[x]); for(int i=x;i<=min(y,bl[x]*size);i++) a[i]=v; init(bl[x]); for(int i=bl[x]+1;i<bl[y];i++){ tag[i]=v; if(v) lc1[i]=rc1[i]=sc1[i]=sum[i]=size,lc0[i]=rc0[i]=sc0[i]=0; else lc1[i]=rc1[i]=sc1[i]=sum[i]=0,lc0[i]=rc0[i]=sc0[i]=size; } if(bl[x]==bl[y]) return; pushdown(bl[y]); for(int i=(bl[y]-1)*size+1;i<=y;i++) a[i]=v; init(bl[y]); } void change2(int x,int y){ pushdown(bl[x]); for(int i=x;i<=min(y,bl[x]*size);i++) a[i]^=1; init(bl[x]); for(int i=bl[x]+1;i<bl[y];i++){ if(tag[i]==-1) tag[i]=2; else if(tag[i]==0) tag[i]=1; else if(tag[i]==1) tag[i]=0; else tag[i]=-1; swap(lc0[i],lc1[i]);swap(rc0[i],rc1[i]); swap(sc0[i],sc1[i]);sum[i]=size-sum[i]; } if(bl[x]==bl[y]) return; pushdown(bl[y]); for(int i=(bl[y]-1)*size+1;i<=y;i++) a[i]^=1; init(bl[y]); } int query1(int x,int y){ int ans=0; pushdown(bl[x]); for(int i=x;i<=min(y,bl[x]*size);i++) if(a[i]) ans++; for(int i=bl[x]+1;i<bl[y];i++) ans+=sum[i]; if(bl[x]==bl[y]) return ans; pushdown(bl[y]); for(int i=(bl[y]-1)*size+1;i<=y;i++) if(a[i]) ans++; return ans; } int query2(int x,int y){ int ans=0,l=0; pushdown(bl[x]); for(int i=x;i<=min(y,bl[x]*size);i++){ if(a[i]) l++;else l=0; ans=max(ans,l); } for(int i=bl[x]+1;i<bl[y];i++){ l+=lc1[i]; ans=max(ans,l); ans=max(ans,sc1[i]); if(lc1[i]!=size) l=rc1[i]; } if(bl[x]==bl[y]) return max(ans,l); pushdown(bl[y]); for(int i=(bl[y]-1)*size+1;i<=y;i++){ if(a[i]) l++;else l=0; ans=max(ans,l); } return ans; } int main(){ memset(tag,-1,sizeof(tag)); scanf("%d%d",&n,&m);size=sqrt(n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); bl[i]=(i-1)/size+1; } for(int i=1;i<=bl[n];i++) init(i); int op,x,y; for(int i=1;i<=m;i++){ scanf("%d%d%d",&op,&x,&y);x++;y++; if(op==0) change1(x,y,0); if(op==1) change1(x,y,1); if(op==2) change2(x,y); if(op==3) printf("%d\n",query1(x,y)); if(op==4) printf("%d\n",query2(x,y)); } return 0; }
序列操作(bzoj 1858)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。