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
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
Source
比较简单的用线段树维护的题目。
前面几个都比较简单。
反正都是下放一个tag,细节注意一下就好了。
还有就是要注意2操作的优先级应该低于0,1操作!
0,1操作更新完后就把2操作的标记清零。
2操作,1和0互换,只要把它们的信息也互换即可。
而4操作比较麻烦,不过BZOJ 1500
其中的最后一个要求有些类似。
我们也是记录左端连续个数lx,右端rx,以及中间最长连续的mx。
然后维护的时候有一些不同,不过只要分类讨论即可。
下文假设lx,rx,mx均指1的连续长度。
注意一下比如1110中,11的lx为2,10的lx为1。
类似于这种样例要注意特判。
具体的维护简单想一下就好了……还是比较简单的。。
#include<bits/stdc++.h>
#define pr(a,b,c) {a,b,c}
using namespace std;
int read(){
int x=0,f=1;char ch=getchar();
while (ch<'0' || ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
const int
MAX=100005;
int n,m;
struct Segment{
int Num[2],lx[2],rx[2],mx[2];
int TAG;
bool rev,tag;
}tr[MAX<<2];
struct Query2{
int lx,mx,rx;
};
void up(int u,int L,int R){
int l=u<<1,r=u<<1|1,mid=(L+R)>>1;
for (int i=0;i<2;i++){
tr[u].Num[i]=tr[l].Num[i]+tr[r].Num[i];
tr[u].mx[i]=max(max(tr[r].mx[i],tr[l].rx[i]+tr[r].lx[i]),tr[l].mx[i]);
tr[u].lx[i]=tr[l].lx[i];
if (tr[l].lx[i]==mid-L+1) tr[u].lx[i]+=tr[r].lx[i];
tr[u].rx[i]=tr[r].rx[i];
if (tr[r].rx[i]==R-mid) tr[u].rx[i]+=tr[l].rx[i];
}
}
void Swap(int id){
swap(tr[id].Num[0],tr[id].Num[1]);
swap(tr[id].lx[0],tr[id].lx[1]);
swap(tr[id].rx[0],tr[id].rx[1]);
swap(tr[id].mx[0],tr[id].mx[1]);
}
void Tag(int id,int num,int l,int r){
tr[id].Num[num]=r-l+1;
tr[id].Num[num^1]=0;
tr[id].lx[0]=tr[id].rx[0]=tr[id].mx[0]=(r-l+1)*(num==0);
tr[id].lx[1]=tr[id].rx[1]=tr[id].mx[1]=(r-l+1)*(num==1);
tr[id].TAG=num;
tr[id].tag=1;
tr[id].rev=0;
}
void down(int u,int L,int R){
if (tr[u].tag){
int l=u<<1,r=u<<1|1,mid=(L+R)>>1;
Tag(l,tr[u].TAG,L,mid);
Tag(r,tr[u].TAG,mid+1,R);
tr[u].tag=0;
}
if (tr[u].rev){
int l=u<<1,r=u<<1|1;
tr[l].rev^=1,Swap(l);
tr[r].rev^=1,Swap(r);
tr[u].rev=0;
}
}
void updateAll(int id,int l,int r,int gl,int gr,int num){
if (l>=gl && r<=gr){
Tag(id,num,l,r);
return;
}
down(id,l,r);
int mid=(l+r)>>1;
if (gr<=mid) updateAll(id<<1,l,mid,gl,gr,num); else
if (gl>mid) updateAll(id<<1|1,mid+1,r,gl,gr,num);
else{
updateAll(id<<1,l,mid,gl,mid,num);
updateAll(id<<1|1,mid+1,r,mid+1,gr,num);
}
up(id,l,r);
}
void reverseAll(int id,int l,int r,int gl,int gr){
if (l>=gl && r<=gr){
tr[id].rev^=1;
Swap(id);
return;
}
down(id,l,r);
int mid=(l+r)>>1;
if (gr<=mid) reverseAll(id<<1,l,mid,gl,gr); else
if (gl>mid) reverseAll(id<<1|1,mid+1,r,gl,gr);
else{
reverseAll(id<<1,l,mid,gl,mid);
reverseAll(id<<1|1,mid+1,r,mid+1,gr);
}
up(id,l,r);
}
int query1(int id,int l,int r,int gl,int gr){
if (l>=gl && r<=gr) return tr[id].Num[1];
down(id,l,r);
int mid=(l+r)>>1,t1;
if (gr<=mid) t1=query1(id<<1,l,mid,gl,gr); else
if (gl>mid) t1=query1(id<<1|1,mid+1,r,gl,gr);
else
t1=query1(id<<1,l,mid,gl,mid)+query1(id<<1|1,mid+1,r,mid+1,gr);
return t1;
}
Query2 query2(int id,int l,int r,int gl,int gr){
if (l>=gl && r<=gr) return (Query2){tr[id].lx[1],tr[id].mx[1],tr[id].rx[1]};
down(id,l,r);
int mid=(l+r)>>1;
Query2 t1={0,0,0},t2={0,0,0};
if (gr<=mid) t1=query2(id<<1,l,mid,gl,gr); else
if (gl>mid) t2=query2(id<<1|1,mid+1,r,gl,gr);
else
t1=query2(id<<1,l,mid,gl,mid),
t2=query2(id<<1|1,mid+1,r,mid+1,gr);
if (t1.lx==mid-l+1) t1.lx+=t2.lx;
if (t2.rx==r-mid) t2.rx+=t1.rx;
return (Query2){t1.lx,max(max(t1.mx,t2.mx),t1.rx+t2.lx),t2.rx};
}
int main(){
n=read(),m=read();
for (int i=1;i<=n;i++)
updateAll(1,1,n,i,i,read());
int opt,a,b;
while (m--){
opt=read(),a=read(),b=read();
a++,b++;
if (!opt) updateAll(1,1,n,a,b,0);
if (opt==1) updateAll(1,1,n,a,b,1);
if (opt==2) reverseAll(1,1,n,a,b);
if (opt==3) printf("%d\n",query1(1,1,n,a,b));
if (opt==4) printf("%d\n",query2(1,1,n,a,b).mx);
}
return 0;
}