线段树裸(shen)题……
题意:对01串进行五种操作:0、清零;1、清一;2、取反(flip);3、询问区间内'1'的个数;4、询问区间内最多的连续的'1'的个数。
果然,看完前四个操作,我感觉我看到了一个 bitset 裸题~。既然有了第五个操作,则改用线段树:
对于每一段区间,维护下列信息:
左/右端点数值 leftnum/rightnum(0/1);
左/右起最长连续元素个数 llen/rlen(0/1不限,关于区间属性使用leftnum/rightnum判断);
区间内最长连续的0/1的个数 len[][0]/len[][1];
区间内1的数量 sum;
清数值/取反标记 lazy_num/lazy_flip;
每一个节点的leftnum/rightnum和子节点信息相同,llen、rlen、len[][0]\len[][1]信息可由其子节点信息分类讨论得到。
每一个取反操作需swap(len[pos][0],len[pos][1]),llen和rlen不需更新。
另外,只有注意细节,此题方能AC~
这是我迄今为止除交表外代码最长的一题~~我是蒟蒻沙茶~~
[Scoi2010]序列操作 C++代码实现:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define lson pos<<1
#define rson pos<<1|1
#define N 100010
int n,m;
int a[N];
int leftnum[4*N],rightnum[4*N],llen[4*N],rlen[4*N],len[4*N][2],sum[4*N],lazy_num[4*N],lazy_flip[4*N];
inline void maintain(int pos,int l,int r)
{
int mid=(l+r)>>1;
sum[pos]=sum[lson]+sum[rson];
leftnum[pos]=leftnum[lson];
rightnum[pos]=rightnum[rson];
llen[pos]=(llen[lson]==mid-l+1&&rightnum[lson]==leftnum[rson])?llen[lson]+llen[rson]:llen[lson];
rlen[pos]=(rlen[rson]==r-mid&&leftnum[rson]==rightnum[lson])?rlen[rson]+rlen[lson]:rlen[rson];
len[pos][0]=max(len[lson][0],len[rson][0]);
len[pos][1]=max(len[lson][1],len[rson][1]);
if(rightnum[lson]==leftnum[rson]) len[pos][rightnum[lson]]=max(len[pos][rightnum[lson]],rlen[lson]+llen[rson]);
}
inline void lazy(int pos,int l,int r)
{
int mid=(l+r)>>1;
if(lazy_num[pos]>=0)
{
lazy_num[lson]=lazy_num[rson]=lazy_num[pos];
lazy_flip[lson]=lazy_flip[rson]=0;
leftnum[lson]=rightnum[lson]=leftnum[rson]=rightnum[rson]=lazy_num[pos];
llen[lson]=rlen[lson]=len[lson][lazy_num[pos]]=mid-l+1;llen[rson]=rlen[rson]=len[rson][lazy_num[pos]]=r-mid;
len[lson][lazy_num[pos]^1]=len[rson][lazy_num[pos]^1]=0;
sum[lson]=(mid-l+1)*lazy_num[pos];sum[rson]=(r-mid)*lazy_num[pos];
lazy_num[pos]=-1;
}
if(lazy_flip[pos])
{
lazy_flip[pos]=0;
if(lazy_num[lson]>=0) lazy_num[lson]^=1;
else lazy_flip[lson]^=1;
if(lazy_num[rson]>=0) lazy_num[rson]^=1;
else lazy_flip[rson]^=1;
leftnum[lson]^=1;rightnum[lson]^=1;
leftnum[rson]^=1;rightnum[rson]^=1;
swap(len[lson][0],len[lson][1]);
swap(len[rson][0],len[rson][1]);
sum[lson]=(mid-l+1-sum[lson]);
sum[rson]=(r-mid-sum[rson]);
}
}
void build(int pos,int l,int r)
{
lazy_num[pos]=-1;
if(l==r)
{
leftnum[pos]=rightnum[pos]=sum[pos]=a[l];
llen[pos]=rlen[pos]=1;
len[pos][a[l]]=1;
return;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
maintain(pos,l,r);
}
void clear(int pos,int l,int r,int x,int y,int z)
{
if(x<=l&&r<=y)
{
lazy_flip[pos]=0;
leftnum[pos]=rightnum[pos]=lazy_num[pos]=z;
llen[pos]=rlen[pos]=len[pos][z]=r-l+1;
len[pos][z^1]=0;
sum[pos]=(r-l+1)*z;
return;
}
if(lazy_num[pos]>=0||lazy_flip[pos])
lazy(pos,l,r);
int mid=(l+r)>>1;
if(y<=mid) clear(lson,l,mid,x,y,z);
else if(x>mid) clear(rson,mid+1,r,x,y,z);
else clear(lson,l,mid,x,y,z),clear(rson,mid+1,r,x,y,z);
maintain(pos,l,r);
}
void flip(int pos,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
if(lazy_num[pos]>=0) lazy_num[pos]^=1;
else lazy_flip[pos]^=1;
leftnum[pos]^=1;
rightnum[pos]^=1;
swap(len[pos][0],len[pos][1]);
sum[pos]=(r-l+1-sum[pos]);
return;
}
if(lazy_num[pos]>=0||lazy_flip[pos])
lazy(pos,l,r);
int mid=(l+r)>>1;
if(y<=mid) flip(lson,l,mid,x,y);
else if(x>mid) flip(rson,mid+1,r,x,y);
else flip(lson,l,mid,x,y),flip(rson,mid+1,r,x,y);
maintain(pos,l,r);
}
int query_sum(int pos,int l,int r,int x,int y)
{
if(x<=l&&r<=y) return sum[pos];
if(lazy_num[pos]>=0||lazy_flip[pos])
lazy(pos,l,r);
int mid=(l+r)>>1;
if(y<=mid) return query_sum(lson,l,mid,x,y);
if(x>mid) return query_sum(rson,mid+1,r,x,y);
return query_sum(lson,l,mid,x,y)+query_sum(rson,mid+1,r,x,y);
}
int query_llen(int pos,int l,int r,int x)
{
if(r<=x) return llen[pos];
if(lazy_num[pos]>=0||lazy_flip[pos])
lazy(pos,l,r);
int mid=(l+r)>>1;
if(x>mid) return (llen[lson]==mid-l+1&&rightnum[lson]==leftnum[rson])?llen[lson]+query_llen(rson,mid+1,r,x):llen[lson];
return query_llen(lson,l,mid,x);
}
int query_rlen(int pos,int l,int r,int x)
{
if(x<=l) return rlen[pos];
if(lazy_num[pos]>=0||lazy_flip[pos])
lazy(pos,l,r);
int mid=(l+r)>>1;
if(x<=mid) return (rlen[rson]==r-mid&&leftnum[rson]==rightnum[lson])?rlen[rson]+query_rlen(lson,l,mid,x):rlen[rson];
return query_rlen(rson,mid+1,r,x);
}
int query_len(int pos,int l,int r,int x,int y)
{
if(x<=l&&r<=y) return len[pos][1];
if(lazy_num[pos]>=0||lazy_flip[pos])
lazy(pos,l,r);
int mid=(l+r)>>1;
if(y<=mid) return query_len(lson,l,mid,x,y);
if(x>mid) return query_len(rson,mid+1,r,x,y);
if(rightnum[lson]==1&&leftnum[rson]==1)
return max(query_rlen(lson,l,mid,x)+query_llen(rson,mid+1,r,y),max(query_len(lson,l,mid,x,y),query_len(rson,mid+1,r,x,y)));
return max(query_len(lson,l,mid,x,y),query_len(rson,mid+1,r,x,y));
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,1,n);
for(int opt,x,y,i=1;i<=m;i++)
{
scanf("%d%d%d",&opt,&x,&y);
x++;y++;
if(opt==0)
clear(1,1,n,x,y,0);
else if(opt==1)
clear(1,1,n,x,y,1);
else if(opt==2)
flip(1,1,n,x,y);
else if(opt==3)
printf("%d\n",query_sum(1,1,n,x,y));
else printf("%d\n",query_len(1,1,n,x,y));
}
return 0;
}