【題目描述】
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
這題真心煩,尤其是對初學線段樹的我來說。考試的時候不得不強行寫了30分的程序(o(╯□╰)o)。調了一天了,到晚上才調出來,我果然是蒟蒻。
`此處我用的是姜神的思路,又省空間又省時間,真的好。 nod數組代表lazy,如果下面區間數字一致,
可代表 0or1時:update&pushdown 沒什麼難度。
2時:+一個如果區間不相等,再往下就是了
3時:查詢左右即可。
4時:用一個last數組存儲前一個區間的值,更新max即可。
如果有什麼地方不(wan)清(quan)楚(mei)的(xie),請參見 jiangzh的blog:http://www.xuebuyuan.com/1960418.html
#include<cstdio>
#include<cstring>
#include<iostream>
#define push_up if (nod[rt<<1]==nod[rt<<1|1]&&nod[rt]==-1) nod[rt]=nod[rt<<1]
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
using namespace std;
int nod[800005],n,m,last,max1,ans,a;
void init()
{
freopen("operation.in","r",stdin);
freopen("operation.out","w",stdout);
}
void pushdown(int rt)
{
if (nod[rt]!=-1)
{
nod[rt<<1]=nod[rt<<1|1]=nod[rt];
nod[rt]=-1;
}
}
void change(int rt,int l,int r,int a,int b,int color)
{
if (a<=l&&b>=r)
{
nod[rt]=color;
return;
}
pushdown(rt);
int mid=(l+r)>>1;
if (a<=mid) change(lson,a,b,color);
if (b>mid) change(rson,a,b,color);
push_up;
}
void modity(int rt,int l,int r,int a,int b)
{
if (a<=l&&b>=r)
{
if (nod[rt]!=-1)
{
nod[rt]=1-nod[rt];
return;
}
}
pushdown(rt);
int mid=(l+r)>>1;
if (a<=mid) modity(lson,a,b);
if (b>mid) modity(rson,a,b);
push_up;
}
int count(int rt,int l,int r,int a,int b)
{
if (a<=l&&b>=r)
{
if (nod[rt]==1) return r-l+1;
else if (nod[rt]==0)return 0;
}
pushdown(rt);
int mid=(l+r)>>1;
int x1=0;
int x2=0;
if (a<=mid) x1=count(lson,a,b);
if (b>mid) x2=count(rson,a,b);
push_up;
return x1+x2;
}
void find(int rt,int l,int r,int a,int b)
{
if (a<=l&&b>=r)
{
if (nod[rt]!=-1)
{
if (nod[rt]==1&&last==1)
{
max1+=r-l+1;
ans=max(max1,ans);
}
else if (nod[rt]==1&&last==0)
{
max1=r-l+1;
ans=max(max1,ans);
}
else if (nod[rt]==0)
{
max1=0;
}
ans=max(max1,ans);
last=nod[rt];
return;
}
if (l==r) return;
}
pushdown(rt);
int mid=(l+r)>>1;
if (a<=mid) find(lson,a,b);
if (b>mid) find(rson,a,b);
push_up;
}
void work()
{
cin>>n>>m;
int x,y,z;
for (int i=0;i<n;i++)
{
scanf("%d",&a);
change(1,0,n-1,i,i,a);
}
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
if (x==0||x==1) change(1,0,n-1,y,z,x);
if (x==2) modity(1,0,n-1,y,z);
if (x==3) printf("%d\n",count(1,0,n-1,y,z));
if (x==4)
{
last=1;
max1=ans=0;
find(1,0,n-1,y,z);
printf("%d\n",ans);
}
}
}
int main()
{
init();
work();
return 0;
}