[BZOJ1858] [Scoi2010]序列操作

题目描述

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

题目分析

真是该AFO了 从第一份代码里调出了不下10个严重bug......

线段树维护l[0],l[1],r[0],r[1],all[0],all[1],sum
代表从左端点开始的连续0的个数左端点开始的连续1的个数从右端点开始的连续0的个数右端点开始的连续1的个数
区间最大连续0的个数区间最大连续1的个数区间和(区间内1的个数)
然后推一推就好了
写的代码及其恶心QAQ

#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
int n,m;
int val[101000];
struct your
{
    int x,y;
    int cover,add;
    int sum;
    int l[3],r[3],all[3];
}a[401000];
int cnt;
void add_pushdown(int num)
{
    a[num<<1].add=a[num<<1|1].add=a[num].add;
    a[num<<1].sum=(a[num<<1].y-a[num<<1].x+1)*a[num].add;
    a[num<<1|1].sum=(a[num<<1|1].y-a[num<<1|1].x+1)*a[num].add;
    a[num<<1].l[a[num].add]=a[num<<1].r[a[num].add]=a[num<<1].all[a[num].add]=a[num<<1].y-a[num<<1].x+1;
    a[num<<1|1].l[a[num].add]=a[num<<1|1].r[a[num].add]=a[num<<1|1].all[a[num].add]=a[num<<1|1].y-a[num<<1|1].x+1;
    a[num].add^=1;
    a[num<<1].l[a[num].add]=a[num<<1|1].l[a[num].add]=a[num<<1].r[a[num].add]=a[num<<1|1].r[a[num].add]=a[num<<1].all[a[num].add]=a[num<<1|1].all[a[num].add]=0;
    a[num].cover=a[num<<1].cover=a[num<<1|1].cover=0;
    a[num].add=-1;
}
void cover_pushdown(int num)
{
    a[num<<1].sum=(a[num<<1].y-a[num<<1].x+1)-a[num<<1].sum;
    a[num<<1|1].sum=(a[num<<1|1].y-a[num<<1|1].x+1)-a[num<<1|1].sum;
    swap(a[num<<1].l[0],a[num<<1].l[1]),swap(a[num<<1|1].l[0],a[num<<1|1].l[1]);
    swap(a[num<<1].r[0],a[num<<1].r[1]),swap(a[num<<1|1].r[0],a[num<<1|1].r[1]);
    swap(a[num<<1].all[0],a[num<<1].all[1]),swap(a[num<<1|1].all[0],a[num<<1|1].all[1]);
    if(a[num<<1].add!=-1) a[num<<1].add^=1; 
        else a[num<<1].cover^=1;
    if(a[num<<1|1].add!=-1) a[num<<1|1].add^=1; 
        else a[num<<1|1].cover^=1;
    a[num].cover=0;
}
void push_up(int num)
{
    a[num].sum=a[num<<1].sum+a[num<<1|1].sum;
    a[num].l[0]=(a[num<<1].l[0]==(a[num<<1].y-a[num<<1].x+1))?a[num<<1|1].l[0]+a[num<<1].l[0]:a[num<<1].l[0];
    a[num].l[1]=(a[num<<1].l[1]==(a[num<<1].y-a[num<<1].x+1))?a[num<<1|1].l[1]+a[num<<1].l[1]:a[num<<1].l[1];
    a[num].r[0]=(a[num<<1|1].r[0]==(a[num<<1|1].y-a[num<<1|1].x+1))?a[num<<1].r[0]+a[num<<1|1].r[0]:a[num<<1|1].r[0];
    a[num].r[1]=(a[num<<1|1].r[1]==(a[num<<1|1].y-a[num<<1|1].x+1))?a[num<<1].r[1]+a[num<<1|1].r[1]:a[num<<1|1].r[1];
    a[num].all[0]=max(max(a[num<<1].all[0],a[num<<1|1].all[0]),a[num<<1].r[0]+a[num<<1|1].l[0]);
    a[num].all[1]=max(max(a[num<<1].all[1],a[num<<1|1].all[1]),a[num<<1].r[1]+a[num<<1|1].l[1]);
    return ;
}
void build(int dx,int dy,int num)
{
    cnt++;
    a[num].x=dx,a[num].y=dy;
    a[num].add=-1;
    if(dx==dy) 
    {
        a[num].sum=val[dx];
        a[num].l[val[dx]]=a[num].r[val[dx]]=a[num].all[val[dx]]=1;
        return ;    
    }
    int mid=(dx+dy)>>1;
    build(dx,mid,num<<1),build(mid+1,dy,num<<1|1);
    push_up(num);
}
void update(int dx,int dy,int c,int num)
{
    if(a[num].x==dx&&a[num].y==dy)
    {
        a[num].add=c;
        a[num].sum=(a[num].y-a[num].x+1)*c;
        a[num].l[c]=a[num].r[c]=a[num].all[c]=a[num].y-a[num].x+1;
        a[num].l[c^1]=a[num].r[c^1]=a[num].all[c^1]=0;
        a[num].cover=0;  
        return ;
    }
    if(a[num].add!=-1) add_pushdown(num);
    if(a[num].cover) cover_pushdown(num);
    int mid=(a[num].x+a[num].y)>>1;
    if(dx>mid) update(dx,dy,c,num<<1|1);
    else if(dy<=mid) update(dx,dy,c,num<<1);
    else update(dx,mid,c,num<<1),update(mid+1,dy,c,num<<1|1);
    push_up(num);
}
void cover(int dx,int dy,int num)
{
    if(a[num].x==dx&&a[num].y==dy)
    {
        a[num].sum=(a[num].y-a[num].x+1)-a[num].sum;
        swap(a[num].l[0],a[num].l[1]);
        swap(a[num].r[0],a[num].r[1]);
        swap(a[num].all[0],a[num].all[1]);
        if(a[num].add!=-1) a[num].add^=1;
        else a[num].cover^=1;
        return ;
    }
    if(a[num].add!=-1) add_pushdown(num);
    if(a[num].cover) cover_pushdown(num);
    int mid=(a[num].x+a[num].y)>>1;
    if(dx>mid) cover(dx,dy,num<<1|1);
    else if(dy<=mid) cover(dx,dy,num<<1);
    else cover(dx,mid,num<<1),cover(mid+1,dy,num<<1|1);
    push_up(num);
}
int ask(int dx,int dy,int num,int color)
{
    if(a[num].x==dx&&a[num].y==dy) 
        return !color?a[num].sum:a[num].all[1];
    if(a[num].add!=-1) add_pushdown(num);
    if(a[num].cover) cover_pushdown(num);
    int mid=(a[num].x+a[num].y)>>1;
    if(dx>mid) return ask(dx,dy,num<<1|1,color);
    if(dy<=mid) return ask(dx,dy,num<<1,color);
    if(!color) return ask(dx,mid,num<<1,color)+ask(mid+1,dy,num<<1|1,color);
    else 
    {
        int tmp=max(ask(dx,mid,num<<1,color),ask(mid+1,dy,num<<1|1,color));
        int nmp=min(mid-dx+1,a[num<<1].r[1])+min(dy-mid,a[num<<1|1].l[1]);
        return max(tmp,nmp);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    build(1,n,1);
    for(int i=1;i<=m;i++)
    {
        int tmp,x,y;
        scanf("%d%d%d",&tmp,&x,&y);
        x++,y++;
        if(tmp==0) update(x,y,0,1);
        else if(tmp==1) update(x,y,1,1);
        else if(tmp==2) cover(x,y,1);
        else if(tmp==3) printf("%d\n",ask(x,y,1,0));
        else if(tmp==4) printf("%d\n",ask(x,y,1,1));
    }
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注