题目描述
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都需要给出回答,聪明的程序员们,你们能帮助他吗?
输入输出格式
输入格式:输入数据第一行包括2个数,n和m,分别表示序列的长度和操作数目
第二行包括n个数,表示序列的初始状态
接下来m行,每行3个数,op, a, b,(0<=op<=4,0<=a<=b<n)表示对于区间[a, b]执行标号为op的操作
对于每一个询问操作,输出一行,包括1个数,表示其对应的答案
输入输出样例
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
5 2 6 5
说明
对于30%的数据,1<=n, m<=1000
对于100%的数据,1<=n, m<=100000
看到 区间修改+区间查询。。。
去吧,线段树。。。
于是一个晚上就没了。。。
恶心啊。。。
线段树记录:
区间和值;
区间最长0、1的长度;
从左端点开始最长0、1的长度,葱油断电开始最长0、1的长度;
两个标记:全赋0/1,取反;
左右端点。
3很好做,4呢?
所以求4时,返回的不是一个值,而是一个线段树节点。
修改时,若正在改某区间的 全赋0/1 标记,记得将 取反 标记清0,巨坑。。。
还有上传,下传很重要,但是太恶心,不想多说,看代码吧。。。
附代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#define LSON rt<<1
#define RSON rt<<1|1
#define DATA(x) a[x].data
#define SIGN1(x) a[x].c
#define SIGN2(x) a[x].v
#define SUM1(x) a[x].sum1
#define SUM2(x) a[x].sum2
#define LEFT1(x) a[x].left1
#define LEFT2(x) a[x].left2
#define RIGHT1(x) a[x].right1
#define RIGHT2(x) a[x].right2
#define LSIDE(x) a[x].l
#define RSIDE(x) a[x].r
#define WIDTH(x) (RSIDE(x)-LSIDE(x)+1)
#define MAXN 100010
using namespace std;
int n,m;
struct node{
int data,c,v,left1,right1,sum1,left2,right2,sum2;
int l,r;
}a[MAXN<<2];
inline int read(){
int date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
void pushup(int rt){
DATA(rt)=DATA(LSON)+DATA(RSON);
SUM1(rt)=max(RIGHT1(LSON)+LEFT1(RSON),max(SUM1(LSON),SUM1(RSON)));
SUM2(rt)=max(RIGHT2(LSON)+LEFT2(RSON),max(SUM2(LSON),SUM2(RSON)));
LEFT1(rt)=LEFT1(LSON);RIGHT1(rt)=RIGHT1(RSON);
LEFT2(rt)=LEFT2(LSON);RIGHT2(rt)=RIGHT2(RSON);
if(LEFT1(LSON)==WIDTH(LSON))LEFT1(rt)+=LEFT1(RSON);
if(LEFT2(LSON)==WIDTH(LSON))LEFT2(rt)+=LEFT2(RSON);
if(RIGHT1(RSON)==WIDTH(RSON))RIGHT1(rt)+=RIGHT1(LSON);
if(RIGHT2(RSON)==WIDTH(RSON))RIGHT2(rt)+=RIGHT2(LSON);
}
void pushdown(int rt){
if(LSIDE(rt)==RSIDE(rt))return;
if(SIGN1(rt)!=-1){
SIGN1(LSON)=SIGN1(rt);
SIGN2(LSON)=0;
DATA(LSON)=SUM2(LSON)=LEFT2(LSON)=RIGHT2(LSON)=SIGN1(rt)*WIDTH(LSON);
SUM1(LSON)=LEFT1(LSON)=RIGHT1(LSON)=(SIGN1(rt)^1)*WIDTH(LSON);
SIGN1(RSON)=SIGN1(rt);
SIGN2(RSON)=0;
DATA(RSON)=SUM2(RSON)=LEFT2(RSON)=RIGHT2(RSON)=SIGN1(rt)*WIDTH(RSON);
SUM1(RSON)=LEFT1(RSON)=RIGHT1(RSON)=(SIGN1(rt)^1)*WIDTH(RSON);
SIGN1(rt)=-1;
}
if(SIGN2(rt)){
SIGN2(LSON)^=1;
DATA(LSON)=WIDTH(LSON)-DATA(LSON);
swap(SUM1(LSON),SUM2(LSON));
swap(LEFT1(LSON),LEFT2(LSON));swap(RIGHT1(LSON),RIGHT2(LSON));
SIGN2(RSON)^=1;
DATA(RSON)=WIDTH(RSON)-DATA(RSON);
swap(SUM1(RSON),SUM2(RSON));
swap(LEFT1(RSON),LEFT2(RSON));swap(RIGHT1(RSON),RIGHT2(RSON));
SIGN2(rt)=0;
}
}
void buildtree(int l,int r,int rt){
int mid;
LSIDE(rt)=l;RSIDE(rt)=r;
SIGN1(rt)=-1;SIGN2(rt)=0;
if(l==r){
int x=read();
DATA(rt)=LEFT2(rt)=RIGHT2(rt)=SUM2(rt)=x;
LEFT1(rt)=RIGHT1(rt)=SUM1(rt)=x^1;
return;
}
mid=l+r>>1;
buildtree(l,mid,LSON);
buildtree(mid+1,r,RSON);
pushup(rt);
}
void update_all(int l,int r,int c,int rt){
int mid;
if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
SIGN1(rt)=c;
SIGN2(rt)=0;
DATA(rt)=LEFT2(rt)=RIGHT2(rt)=SUM2(rt)=c*WIDTH(rt);
LEFT1(rt)=RIGHT1(rt)=SUM1(rt)=(c^1)*WIDTH(rt);
pushdown(rt);
return;
}
pushdown(rt);
mid=LSIDE(rt)+RSIDE(rt)>>1;
if(l<=mid)update_all(l,r,c,LSON);
if(mid<r)update_all(l,r,c,RSON);
pushup(rt);
}
void update_false(int l,int r,int rt){
int mid;
if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
SIGN2(rt)^=1;
DATA(rt)=WIDTH(rt)-DATA(rt);
swap(SUM1(rt),SUM2(rt));
swap(LEFT1(rt),LEFT2(rt));swap(RIGHT1(rt),RIGHT2(rt));
pushdown(rt);
return;
}
pushdown(rt);
mid=LSIDE(rt)+RSIDE(rt)>>1;
if(l<=mid)update_false(l,r,LSON);
if(mid<r)update_false(l,r,RSON);
pushup(rt);
}
int query_all(int l,int r,int rt){
int mid,ans=0;
if(l<=LSIDE(rt)&&RSIDE(rt)<=r)
return DATA(rt);
pushdown(rt);
mid=LSIDE(rt)+RSIDE(rt)>>1;
if(l<=mid)ans+=query_all(l,r,LSON);
if(mid<r)ans+=query_all(l,r,RSON);
return ans;
}
node query_length(int l,int r,int rt){
int mid;
if(l<=LSIDE(rt)&&RSIDE(rt)<=r)
return a[rt];
pushdown(rt);
mid=LSIDE(rt)+RSIDE(rt)>>1;
node ans,ls,rs;
ans=ls=rs=(node){0,0,0,0,0,0,0,0,0,0,0};
if(l<=mid)ls=query_length(l,r,LSON);
if(mid<r)rs=query_length(l,r,RSON);
ans.sum1=max(ls.right1+rs.left1,max(ls.sum1,rs.sum1));
ans.sum2=max(ls.right2+rs.left2,max(ls.sum2,rs.sum2));
ans.left1=ls.left1;ans.right1=rs.right1;
ans.left2=ls.left2;ans.right2=rs.right2;
if(ls.left1==WIDTH(LSON))ans.left1+=rs.left1;
if(ls.left2==WIDTH(LSON))ans.left2+=rs.left2;
if(rs.right1==WIDTH(RSON))ans.right1+=ls.right1;
if(rs.right2==WIDTH(RSON))ans.right2+=ls.right2;
return ans;
}
int main(){
int f,x,y;
n=read();m=read();
buildtree(1,n,1);
while(m--){
f=read();x=read()+1;y=read()+1;
switch(f){
case 0:{
update_all(x,y,0,1);
break;
}
case 1:{
update_all(x,y,1,1);
break;
}
case 2:{
update_false(x,y,1);
break;
}
case 3:{
printf("%d\n",query_all(x,y,1));
break;
}
case 4:{
node s=query_length(x,y,1);
printf("%d\n",s.sum2);
break;
}
}
}
return 0;
}