题目链接:
题意:给一个01序列,有5种操作:
(1)0 L R 将[L,R]之间的数字都变成0;
(2)1 L R 将[L,R]之间的数字都变成1;
(3)2 L R 将[L R]之间的数字都取反;
(4)3 L R 询问[L R]之间1的个数;
(5)4 L R 询问[L,R]之间连续1的个数最大是多少
思路:
(1)每个节点信息:
l0,l1:左端开始连续01的个数;
r0,r1:右端开始连续01的个数;
max0,max1:区间内最长连续01的长度;
cnt0,cnt1:区间内01的个数
flag:-1表示无标记,0表示全为0,1表示全为1,2表示取反
(2)不管查询还是更新,最主要的是当前区间的flag不是-1时,向下传递该状态。
struct node{ int l0,l1,r0,r1,max0,max1,flag,len,cnt0,cnt1; int L,R,mid;};const int MAX=100005;node a[MAX<<2];int n,m,p[MAX];void update(int t){ a[t].l0=a[t*2].l0; if(a[t*2].l0==a[t*2].len) a[t].l0+=a[t*2+1].l0; a[t].r0=a[t*2+1].r0; if(a[t*2+1].r0==a[t*2+1].len) a[t].r0+=a[t*2].r0; a[t].max0=max(a[t*2].max0,a[t*2+1].max0); a[t].max0=max(a[t].max0,a[t*2].r0+a[t*2+1].l0); a[t].cnt0=a[t*2].cnt0+a[t*2+1].cnt0; a[t].l1=a[t*2].l1; if(a[t*2].l1==a[t*2].len) a[t].l1+=a[t*2+1].l1; a[t].r1=a[t*2+1].r1; if(a[t*2+1].r1==a[t*2+1].len) a[t].r1+=a[t*2].r1; a[t].max1=max(a[t*2].max1,a[t*2+1].max1); a[t].max1=max(a[t].max1,a[t*2].r1+a[t*2+1].l1); a[t].cnt1=a[t*2].cnt1+a[t*2+1].cnt1;}void build(int t,int L,int R){ a[t].L=L; a[t].R=R; a[t].mid=(L+R)>>1; a[t].len=R-L+1; a[t].flag=-1; if(L==R) { a[t].l0=a[t].r0=a[t].max0=a[t].cnt0=!p[L]; a[t].l1=a[t].r1=a[t].max1=a[t].cnt1=p[L]; return; } build(t*2,L,a[t].mid); build(t*2+1,a[t].mid+1,R); update(t);}void swap(int &x,int &y){ int temp; temp=x; x=y; y=temp;}void change(int t,int L,int R,int cmd){ if(a[t].L==L&&a[t].R==R) { if(cmd==0) { a[t].l0=a[t].r0=a[t].max0=a[t].cnt0=a[t].len; a[t].l1=a[t].r1=a[t].max1=a[t].cnt1=0; a[t].flag=0; } else if(cmd==1) { a[t].l0=a[t].r0=a[t].max0=a[t].cnt0=0; a[t].l1=a[t].r1=a[t].max1=a[t].cnt1=a[t].len; a[t].flag=1; } else if(cmd==2) { swap(a[t].l0,a[t].l1); swap(a[t].r0,a[t].r1); swap(a[t].cnt0,a[t].cnt1); swap(a[t].max0,a[t].max1); a[t].flag=1-a[t].flag; } return; } if(a[t].flag>=0) { change(t*2,a[t*2].L,a[t*2].R,a[t].flag); change(t*2+1,a[t*2+1].L,a[t*2+1].R,a[t].flag); a[t].flag=-1; } if(R<=a[t].mid) change(t*2,L,R,cmd); else if(L>a[t].mid) change(t*2+1,L,R,cmd); else { change(t*2,L,a[t].mid,cmd); change(t*2+1,a[t].mid+1,R,cmd); } update(t);}node get(int t,int L,int R){ if(a[t].L==L&&a[t].R==R) return a[t]; if(a[t].flag>=0) { change(t*2,a[t*2].L,a[t*2].R,a[t].flag); change(t*2+1,a[t*2+1].L,a[t*2+1].R,a[t].flag); a[t].flag=-1; } node t1,t2,t3; if(R<=a[t].mid) return get(t*2,L,R); else if(L>a[t].mid) return get(t*2+1,L,R); else { t1=get(t*2,L,a[t].mid); t2=get(t*2+1,a[t].mid+1,R); t3.cnt1=t1.cnt1+t2.cnt1; t3.l1=t1.l1; if(t1.l1==t1.len) t3.l1+=t2.l1; t3.r1=t2.r1; if(t2.r1==t2.len) t3.r1+=t1.r1; t3.max1=max(t1.max1,t2.max1); t3.max1=max(t3.max1,t1.r1+t2.l1); t3.len=t1.len+t2.len; return t3; }}int main(){ while(scanf("%d%d",&n,&m)!=-1) { int i; for(i=1;i<=n;i++) scanf("%d",p+i); build(1,1,n); int cmd,L,R; node t; for(i=1;i<=m;i++) { scanf("%d%d%d",&cmd,&L,&R); L++; R++; if(cmd<=2) change(1,L,R,cmd); else { t=get(1,L,R); if(cmd==3) printf("%d\n",t.cnt1); else printf("%d\n",t.max1); } } } return 0;}