1858: [Scoi2010]序列操作
Time Limit: 10 Sec
Memory Limit: 64 MB
Submit: 1031
Solved: 529
[Submit][Status]
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="" style="font-family: arial, verdana, helvetica, sans-serif;">
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
题解:
需要维护4种变量:
1.从左端点最大连续的相同数字
2.从右端点最大连续的相同数字
3.区间内最长连续的相同数字
4.区间内存在多少个相同数字(只是为了操作3)、
因为这个题需要把区间所有数字取反,所以需要同时维护0和1的以上四种量,也就是要维护2*4=8个变量
然后延迟标记要有3种:
1.全0覆盖标记
2.全1覆盖标记
3.区间取反标记
pushup的时候:
1.区间中最长连续的相同数字=max(左区间内最长连续的相同数字,右区间内最长连续的相同数字,左区间右端点最大连续的相同数字+右区间左端点最大连续的相同数字)
2.区间从左右端点最大连续相同数字在pushup的时候要注意,如果左区间或右区间全是1或0的话要特判一下
修改或者pushup的时候:
两种覆盖标记最多存在一个。
当下传了一个区间取反标记:若存在着覆盖标记,则直接将覆盖标记对调;若不存在覆盖标记,直接将区间取反标记异或;
当下传了一个覆盖标记:将其他延迟标记全部清0
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100005;
struct pp {int l,r,c0,c1,ml1,mr1,mx1,ml0,mr0,mx0,len,l1,l0,ln;} T[N*4];
int n,m,a[N];
void pushup(int x)
{
int lc=x<<1,rc=x<<1|1;
T[x].ml1=T[lc].ml1;
T[x].mr1=T[rc].mr1;
if(T[lc].ml1==T[lc].len) T[x].ml1=T[lc].len+T[rc].ml1;
if(T[rc].mr1==T[rc].len) T[x].mr1=T[rc].len+T[lc].mr1;
T[x].ml0=T[lc].ml0;
T[x].mr0=T[rc].mr0;
if(T[lc].ml0==T[lc].len) T[x].ml0=T[lc].len+T[rc].ml0;
if(T[rc].mr0==T[rc].len) T[x].mr0=T[rc].len+T[lc].mr0;
T[x].mx1=max(T[lc].mr1+T[rc].ml1,max(T[lc].mx1,T[rc].mx1));
T[x].mx0=max(T[lc].mr0+T[rc].ml0,max(T[lc].mx0,T[rc].mx0));
T[x].c0=T[lc].c0+T[rc].c0;
T[x].c1=T[lc].c1+T[rc].c1;
}
int e[2];
void pushdown(int x)
{
e[0]=x<<1,e[1]=x<<1|1;
if(T[x].l0)
for(int i=0;i<=1;i++)
{
T[e[i]].ml1=T[e[i]].mr1=T[e[i]].mx1=T[e[i]].c1=0;
T[e[i]].ml0=T[e[i]].mr0=T[e[i]].mx0=T[e[i]].c0=T[e[i]].len;
T[e[i]].l0=1;
T[e[i]].l1=T[e[i]].ln=0;
}
if(T[x].l1)
for(int i=0;i<=1;i++)
{
T[e[i]].ml0=T[e[i]].mr0=T[e[i]].mx0=T[e[i]].c0=0;
T[e[i]].ml1=T[e[i]].mr1=T[e[i]].mx1=T[e[i]].c1=T[e[i]].len;
T[e[i]].l1=1;
T[e[i]].l0=T[e[i]].ln=0;
}
if(T[x].ln)
for(int i=0;i<=1;i++)
{
swap(T[e[i]].ml1,T[e[i]].ml0);
swap(T[e[i]].mr1,T[e[i]].mr0);
swap(T[e[i]].mx1,T[e[i]].mx0);
swap(T[e[i]].c1,T[e[i]].c0);
if(T[e[i]].l1) T[e[i]].l0=1,T[e[i]].l1=0;
else if(T[e[i]].l0) T[e[i]].l1=1,T[e[i]].l0=0;
else T[e[i]].ln^=1;
}
T[x].l1=T[x].l0=T[x].ln=0;
}
void build(int x,int l,int r)
{
T[x].l=l,T[x].r=r;
T[x].len=T[x].r-T[x].l+1;
if(l==r)
{
if(!a[l]) T[x].ml0=T[x].mr0=T[x].mx0=T[x].c0=1;
else T[x].ml1=T[x].mr1=T[x].mx1=T[x].c1=1;
return;
}
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
pushup(x);
}
void Modify(int x,int l,int r,int v)
{
if(T[x].l==l&&T[x].r==r)
{
if(v==3)
{
swap(T[x].ml1,T[x].ml0);
swap(T[x].mr1,T[x].mr0);
swap(T[x].mx1,T[x].mx0);
swap(T[x].c1,T[x].c0);
if(T[x].l1) T[x].l0=1,T[x].l1=0;
else if(T[x].l0) T[x].l1=1,T[x].l0=0;
else T[x].ln^=1;
}
if(v==1)//????0
{
T[x].ml1=T[x].mr1=T[x].mx1=T[x].c1=0;
T[x].ml0=T[x].mr0=T[x].mx0=T[x].c0=T[x].len;
T[x].l0=1;
T[x].l1=T[x].ln=0;
}
if(v==2)//????1
{
T[x].ml0=T[x].mr0=T[x].mx0=T[x].c0=0;
T[x].ml1=T[x].mr1=T[x].mx1=T[x].c1=T[x].len;
T[x].l1=1;
T[x].l0=T[x].ln=0;
}
return;
}
if(T[x].l1||T[x].l0||T[x].ln) pushdown(x);
int mid=(T[x].l+T[x].r)>>1;
if(r<=mid) Modify(x<<1,l,r,v);
else if(l>mid) Modify(x<<1|1,l,r,v);
else Modify(x<<1,l,mid,v),Modify(x<<1|1,mid+1,r,v);
pushup(x);
}
int QueryA(int x,int l,int r)
{
if(T[x].l==l&&T[x].r==r) return T[x].c1;
if(T[x].l1||T[x].l0||T[x].ln) pushdown(x);
int mid=(T[x].l+T[x].r)>>1;
if(r<=mid) return QueryA(x<<1,l,r);
else if(l>mid) return QueryA(x<<1|1,l,r);
else return QueryA(x<<1,l,mid)+QueryA(x<<1|1,mid+1,r);
}
int o,xx,yy;
int QueryC(int x,int l,int r)
{
if(T[x].l==l&&T[x].r==r) return T[x].mx1;
if(T[x].l1||T[x].l0||T[x].ln) pushdown(x);
int mid=(T[x].l+T[x].r)>>1;
if(r<=mid) return QueryC(x<<1,l,r);
else if(l>mid) return QueryC(x<<1|1,l,r);
else return max(min(yy,T[x<<1|1].ml1+mid)-max(xx,mid-T[x<<1].mr1+1)+1,max(QueryC(x<<1,l,mid),QueryC(x<<1|1,mid+1,r)));
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,1,n);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&o,&xx,&yy);
xx++,yy++;
if(o==0) Modify(1,xx,yy,1);
if(o==1) Modify(1,xx,yy,2);
if(o==2) Modify(1,xx,yy,3);
if(o==3) printf("%d\n",QueryA(1,xx,yy));
if(o==4) printf("%d\n",QueryC(1,xx,yy));
}
}