题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397
题意:一个0,1序列,有三种操作方式:1、把某子区间置为0;2、把某子区间置为1;3、把某子区间0,1置反;
有两种询问:1、某子区间中1的个数;2、某子区间连续的1的个数最长是多少
对于第一种询问,就是普通的区间查询,第二种是一个区间合并的过程,可能是左子区间,右子区间或者中间合并一下
对于三种操作,难点在于置反,需要用个lazy标记
我在状态中记录了某个区间中,0和1的个数,区间左边连续的0的个数,区间左边连续的1的个数,右边亦然,以及整个区间的连续的0最长的长度,和1最长的长度
之所以这么做,因为置反后,原来需要查1的,现在查0就好了
结构体的f表示这个区间是否有被置反,x则表示当前应该询问的是什么(x是1,表示这个已经是置反过了的区间,那么本来问1的现在得问0了),因为用的是数组,所以只需询问下标为x^1的即可
每次更新时,如果是前两种操作,那么直接对该区间进行覆盖,这是要将f,x置零,其他的就根据覆盖值是0还是1进行赋值,可以用异或运算,具体可见代码
代码写的很长很丑:
#include
#include
const int MAX = 100010;
struct point
{
int l[2],r[2],max[2],tag,x,sum[2];
int f;
}p[MAX<<2];
int max(int a,int b)
{
return (a>b)?a:b;
}
int min(int a,int b)
{
return (a>1;
if(p[rt].l[p[rt].x]==mid-l+1) p[rt].l[p[rt].x]+=p[rt<<1|1].l[p[rt<<1|1].x];
if(p[rt].r[p[rt].x]==r-mid) p[rt].r[p[rt].x]+=p[rt<<1].r[p[rt<<1].x];
if(p[rt].l[p[rt].x^1]==mid-l+1) p[rt].l[p[rt].x^1]+=p[rt<<1|1].l[p[rt<<1|1].x^1];
if(p[rt].r[p[rt].x^1]==r-mid) p[rt].r[p[rt].x^1]+=p[rt<<1].r[p[rt<<1].x^1];
p[rt].max[p[rt].x] = max(max(p[rt<<1].max[p[rt<<1].x],p[rt<<1|1].max[p[rt<<1|1].x]),p[rt<<1].r[p[rt<<1].x]+p[rt<<1|1].l[p[rt<<1|1].x]);
p[rt].max[p[rt].x^1] = max(max(p[rt<<1].max[p[rt<<1].x^1],p[rt<<1|1].max[p[rt<<1|1].x^1]),p[rt<<1].r[p[rt<<1].x^1]+p[rt<<1|1].l[p[rt<<1|1].x^1]);
p[rt].tag = (p[rt<<1].tag==p[rt<<1|1].tag)?p[rt<<1].tag:-1;
}
void push_down(int l,int r,int rt)
{
int mid = r+l>>1;
if(p[rt].tag!=-1)
{
p[rt<<1].tag = p[rt<<1|1].tag = p[rt].tag;
p[rt<<1].l[p[rt].tag] = p[rt<<1].r[p[rt].tag] = p[rt<<1].max[p[rt].tag] = mid-l+1;
p[rt<<1].l[p[rt].tag^1] = p[rt<<1].r[p[rt].tag^1] = p[rt<<1].max[p[rt].tag^1] = 0;
p[rt<<1|1].l[p[rt].tag] = p[rt<<1|1].r[p[rt].tag] = p[rt<<1|1].max[p[rt].tag] = r-mid;
p[rt<<1|1].l[p[rt].tag^1] = p[rt<<1|1].r[p[rt].tag^1] = p[rt<<1|1].max[p[rt].tag^1] = 0;
p[rt<<1].x = p[rt<<1|1].x = 0;
p[rt<<1].f = p[rt<<1|1].f = 0;
p[rt<<1].sum[p[rt].tag] = mid-l+1;
p[rt<<1].sum[p[rt].tag^1] = 0;
p[rt<<1|1].sum[p[rt].tag] = r-mid;
p[rt<<1|1].sum[p[rt].tag^1] = 0;
}
else if(p[rt].f)
{
if(p[rt<<1].tag!=-1)
{
p[rt<<1].tag^=1;
p[rt<<1].f = 0;
p[rt<<1].x^=1;
}
else
{
p[rt<<1].f ^= 1;
p[rt<<1].x ^= 1;
}
if(p[rt<<1|1].tag!=-1)
{
p[rt<<1|1].tag^=1;
p[rt<<1|1].f = 0;
p[rt<<1|1].x ^= 1;
}
else
{
p[rt<<1|1].f ^= 1;
p[rt<<1|1].x ^= 1;
}
p[rt].f = 0;
}
}
void build(int l,int r,int rt)
{
p[rt].x = p[rt].f = 0;
if(l==r)
{
int x;
scanf("%d",&x);
p[rt].tag = x;
p[rt].l[0] = p[rt].r[0] = p[rt].max[0] = x ^ 1;
p[rt].l[1] = p[rt].r[1] = p[rt].max[1] = x;
p[rt].x = 0;
p[rt].f = 0;
p[rt].sum[x] = 1;
p[rt].sum[x^1] = 0;
return;
}
int mid = l+r>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
push_up(l,r,rt);
}
void update(int flag,int L,int R,int l,int r,int rt)
{
if(L<=l&&R>=r)
{
if(flag<2)
{
p[rt].tag = flag;
p[rt].sum[0] = p[rt].l[0] = p[rt].r[0] = p[rt].max[0] = (flag^1)*(r-l+1);
p[rt].sum[1] = p[rt].l[1] = p[rt].r[1] = p[rt].max[1] = (flag)*(r-l+1);
p[rt].x = 0;
p[rt].f = 0;
}
else
{
p[rt].x ^= 1;
p[rt].f ^= 1;
if(p[rt].tag!=-1)
{
p[rt].tag^=1;
p[rt].f = 0;
}
}
return;
}
int mid = r+l>>1;
push_down(l,r,rt);
if(L<=mid) update(flag,L,R,l,mid,rt<<1);
if(R>mid) update(flag,L,R,mid+1,r,rt<<1|1);
push_up(l,r,rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&R>=r)
return p[rt].max[p[rt].x^1];
int mid = r+l>>1;
push_down(l,r,rt);
int ans = 0;
if(R<=mid) ans = query(L,R,l,mid,rt<<1);
else if(L>mid) ans = query(L,R,mid+1,r,rt<<1|1);
else
{
int tmp = 0;
int l0 = mid-p[rt<<1].r[p[rt<<1].x^1]+1;
int l1 = mid+p[rt<<1|1].l[p[rt<<1|1].x^1];
tmp = min(R,l1)-max(l0,L)+1;
ans = max(max(query(L,R,l,mid,rt<<1),query(L,R,mid+1,r,rt<<1|1)),tmp);
}
// push_up(l,r,rt);
return ans;
}
int query1(int L,int R,int l,int r,int rt)
{
if(L<=l&&R>=r)
return p[rt].sum[p[rt].x^1];
int mid = r+l>>1;
push_down(l,r,rt);
int ans = 0;
if(L<=mid) ans+=query1(L,R,l,mid,rt<<1);
if(R>mid) ans+=query1(L,R,mid+1,r,rt<<1|1);
// push_up(l,r,rt);
return ans;
}
int main()
{
int cas;
scanf("%d",&cas);
while(cas--)
{
int n,m,c,x,y;
scanf("%d%d",&n,&m);
build(0,n-1,1);
while(m--)
{
scanf("%d%d%d",&c,&x,&y);
if(c<3)
update(c,x,y,0,n-1,1);
else if(c==3)
printf("%d\n",query1(x,y,0,n-1,1));
else printf("%d\n",query(x,y,0,n-1,1));
}
}
return 0;
}