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
Sample Output
5
2
6
5
HINT
對於30%的數據,1<=n, m<=1000
對於100%的數據,1<=n, m<=100000
Solution
啊爲什麼調了那麼長時間…
後來發現是push_down操作給子節點標lazy的時候忘記把它們的rev標記去掉了 淚
線段記錄區間裏1和0的個數、最長連續的1和0的個數、左端連續的1和0的個數、右端連續的1和0的個數,然後記錄一個lazy標記和rev標記(取反)。
取反操作的時候遇到lazy標記可以直接對lazy取反,標記lazy的時候要記得把rev去掉
那個最長連續1的詢問函數直接返回了一個結構體,合併操作和線段樹的更新差不多,具體實現看代碼
感覺我沒有辦法寫出優美的代碼,不知道爲什麼代碼長度這麼長= =
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<assert.h>
#define Max(a,b) (a>b?a:b)
#define Min(a,b) (a<b?a:b)
#define mid(a,b) ((a+b)>>1)
#define MAXN 100005
using namespace std;
int n,m;
int x[MAXN],ans;
struct Node{
int l,r,siz;
int num1,lnum1,rnum1,maxnum1;
int num0,lnum0,rnum0,maxnum0;
int lazy,rev;
}t[MAXN*4];
Node operator + (const Node& a,const Node& b)
{
Node ans;
ans.lnum0=a.lnum0;
if(a.lnum0==a.siz)
ans.lnum0=a.siz+b.lnum0;
ans.lnum1=a.lnum1;
if(a.lnum1==a.siz)
ans.lnum1=a.siz+b.lnum1;
ans.rnum0=b.rnum0;
if(b.rnum0==b.siz)
ans.rnum0=b.siz+a.rnum0;
ans.rnum1=b.rnum1;
if(b.rnum1==b.siz)
ans.rnum1=b.siz+a.rnum1;
ans.num0=a.num0+b.num0;
ans.num1=a.num1+b.num1;
ans.maxnum0=Max(a.maxnum0,b.maxnum0);
ans.maxnum0=Max(ans.maxnum0,a.rnum0+b.lnum0);
ans.maxnum1=Max(a.maxnum1,b.maxnum1);
ans.maxnum1=Max(ans.maxnum1,a.rnum1+b.lnum1);
return ans;
}
void _exchange(int idx)
{
swap(t[idx].lnum0,t[idx].lnum1);
swap(t[idx].rnum0,t[idx].rnum1);
swap(t[idx].num0,t[idx].num1);
swap(t[idx].maxnum0,t[idx].maxnum1);
}
void push_down(int idx)
{
if(t[idx].l==t[idx].r)return;
if(t[idx].lazy!=-1)
{
int f=t[idx].lazy;
t[idx*2].lazy=t[idx*2+1].lazy=t[idx].lazy;
t[idx*2].rev=t[idx*2+1].rev=0;
t[idx].lazy=-1;
t[idx*2].lnum0=t[idx*2].rnum0=t[idx*2].num0=t[idx*2].maxnum0=(f==0)*t[idx*2].siz;
t[idx*2].lnum1=t[idx*2].rnum1=t[idx*2].num1=t[idx*2].maxnum1=(f==1)*t[idx*2].siz;
t[idx*2+1].lnum0=t[idx*2+1].rnum0=t[idx*2+1].num0=t[idx*2+1].maxnum0=(f==0)*t[idx*2+1].siz;
t[idx*2+1].lnum1=t[idx*2+1].rnum1=t[idx*2+1].num1=t[idx*2+1].maxnum1=(f==1)*t[idx*2+1].siz;
}
if(t[idx].rev)
{
t[idx].rev=0;
t[idx*2].rev^=1;
t[idx*2+1].rev^=1;
_exchange(idx*2);
_exchange(idx*2+1);
}
}
void _update(int idx)
{
t[idx].lnum0=t[idx*2].lnum0;
if(t[idx*2].lnum0==t[idx*2].siz)
t[idx].lnum0=t[idx*2].siz+t[idx*2+1].lnum0;
t[idx].lnum1=t[idx*2].lnum1;
if(t[idx*2].lnum1==t[idx*2].siz)
t[idx].lnum1=t[idx*2].siz+t[idx*2+1].lnum1;
t[idx].rnum0=t[idx*2+1].rnum0;
if(t[idx*2+1].rnum0==t[idx*2+1].siz)
t[idx].rnum0=t[idx*2+1].siz+t[idx*2].rnum0;
t[idx].rnum1=t[idx*2+1].rnum1;
if(t[idx*2+1].rnum1==t[idx*2+1].siz)
t[idx].rnum1=t[idx*2+1].siz+t[idx*2].rnum1;
t[idx].num0=t[idx*2].num0+t[idx*2+1].num0;
t[idx].num1=t[idx*2].num1+t[idx*2+1].num1;
t[idx].maxnum0=Max(t[idx*2].maxnum0,t[idx*2+1].maxnum0);
t[idx].maxnum0=Max(t[idx].maxnum0,t[idx*2].rnum0+t[idx*2+1].lnum0);
t[idx].maxnum1=Max(t[idx*2].maxnum1,t[idx*2+1].maxnum1);
t[idx].maxnum1=Max(t[idx].maxnum1,t[idx*2].rnum1+t[idx*2+1].lnum1);
}
void _build(int idx,int a,int b)
{
t[idx].siz=b-a+1;
t[idx].l=a;t[idx].r=b;
t[idx].lazy=-1;
t[idx].rev=0;
if(a==b)
{
if(x[a])
{
t[idx].lnum0=t[idx].rnum0=t[idx].num0=t[idx].maxnum0=0;
t[idx].lnum1=t[idx].rnum1=t[idx].num1=t[idx].maxnum1=1;
}
else
{
t[idx].lnum0=t[idx].rnum0=t[idx].num0=t[idx].maxnum0=1;
t[idx].lnum1=t[idx].rnum1=t[idx].num1=t[idx].maxnum1=0;
}
return;
}
int m=mid(a,b);
_build(idx*2,a,m);
_build(idx*2+1,m+1,b);
_update(idx);
}
void _turn(int idx,int a,int b,int f)
{
push_down(idx);
if(t[idx].l==t[idx].r)
{
t[idx].lnum0=t[idx].rnum0=t[idx].num0=t[idx].maxnum0=(f==0);
t[idx].lnum1=t[idx].rnum1=t[idx].num1=t[idx].maxnum1=(f==1);
return;
}
if(a<=t[idx].l&&b>=t[idx].r)
{
t[idx].lnum0=t[idx].rnum0=t[idx].num0=t[idx].maxnum0=(f==0)*t[idx].siz;
t[idx].lnum1=t[idx].rnum1=t[idx].num1=t[idx].maxnum1=(f==1)*t[idx].siz;
if(t[idx].rev)
t[idx].rev=0;
t[idx].lazy=f;
return;
}
int m=mid(t[idx].l,t[idx].r);
if(b<=m)_turn(idx*2,a,b,f);
else if(a>m)_turn(idx*2+1,a,b,f);
else
{
_turn(idx*2,a,b,f);
_turn(idx*2+1,a,b,f);
}
_update(idx);
}
void _reverse(int idx,int a,int b)
{
push_down(idx);
if(t[idx].l==t[idx].r)
{
_exchange(idx);
return;
}
if(a<=t[idx].l&&b>=t[idx].r)
{
if(t[idx].lazy!=-1)
{
t[idx].lazy^=1;
_exchange(idx);
return;
}
t[idx].rev^=1;
_exchange(idx);
return;
}
int m=mid(t[idx].l,t[idx].r);
if(b<=m)_reverse(idx*2,a,b);
else if(a>m)_reverse(idx*2+1,a,b);
else
{
_reverse(idx*2,a,b);
_reverse(idx*2+1,a,b);
}
_update(idx);
}
void _count(int idx,int a,int b)
{
push_down(idx);
if(t[idx].l==t[idx].r)
{
ans+=t[idx].num1;
return;
}
if(a<=t[idx].l&&b>=t[idx].r)
{
ans+=t[idx].num1;
return;
}
int m=mid(t[idx].l,t[idx].r);
if(b<=m)_count(idx*2,a,b);
else if(a>m)_count(idx*2+1,a,b);
else
{
_count(idx*2,a,b);
_count(idx*2+1,a,b);
}
}
Node _query(int idx,int a,int b)
{
push_down(idx);
if(a==t[idx].l&&b==t[idx].r)
{
return t[idx];
}
int m=mid(t[idx].l,t[idx].r);
if(a<=m&&b>m)
{
return _query(idx*2,a,m)+_query(idx*2+1,m+1,b);
}
if(a>m)
{
return _query(idx*2+1,a,b);
}
if(b<=m)
{
return _query(idx*2,a,b);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%d",&x[i]);
_build(1,0,n-1);
for(int i=1;i<=m;i++)
{
int opt,a,b;
scanf("%d%d%d",&opt,&a,&b);
switch(opt)
{
case 0:
_turn(1,a,b,0);break;
case 1:
_turn(1,a,b,1);break;
case 2:
_reverse(1,a,b);break;
case 3:
ans=0;_count(1,a,b);printf("%d\n",ans);break;
case 4:
Node res=_query(1,a,b);
printf("%d\n",res.maxnum1);break;
}
}
return 0;
}