bzoj 1858: [Scoi2010]序列操作

来源:互联网 发布:js淘宝购物车脚本之家 编辑:程序博客网 时间:2024/04/30 20:21

bzoj 1858: [Scoi2010]序列操作

线段树

题意

给一个01串,设计数据结构,支持5种操作:

  1. 区间置零
  2. 区间置一
  3. 区间翻转,0变1,1变0
  4. 查询区间1的个数
  5. 查询区间内最长的连续1的个数

思路

线段树维护连续子区间。就是复杂一点而已。因为有翻转操作,所以要同时维护0和1的信息。
维护区间0、1的个数,区间最长连续0、1,最长前缀0、1,最长后缀0、1。
最好重载+号,pushup就相当于做加法。

代码

#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<map>#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1#define M(a,b) memset(a,b,sizeof(a))using namespace std;const int MAXN=100007;const int oo=0x3f3f3f3f;int max3(int a, int b, int c) { return std::max(std::max(a, b), c); }int num[MAXN];struct Stree{    int flip;//翻转    int num0, num1;//0的个数,1的个数    int set0, set1;//置0,置1    int pre0, pre1;//连续前缀0,连续前缀1    int suf0, suf1;//连续后缀0,连续后缀1    int ma0, ma1;//最长连续0,最长连续1    inline void init() { flip=num0=num1=set0=set1=pre0=pre1=suf0=suf1=ma0=ma1=0; }}stree[MAXN<<2];void pushup(int l, int r, int rt){    stree[rt].num0=stree[rt<<1].num0+stree[rt<<1|1].num0;    stree[rt].num1=stree[rt<<1].num1+stree[rt<<1|1].num1;    stree[rt].ma0=max3(stree[rt<<1].ma0, stree[rt<<1|1].ma0, stree[rt<<1].suf0+stree[rt<<1|1].pre0);    stree[rt].ma1=max3(stree[rt<<1].ma1, stree[rt<<1|1].ma1, stree[rt<<1].suf1+stree[rt<<1|1].pre1);    int mid=(l+r)>>1;    if(stree[rt<<1].pre0==mid-l+1)        stree[rt].pre0=stree[rt<<1].pre0+stree[rt<<1|1].pre0;    else stree[rt].pre0=stree[rt<<1].pre0;    if(stree[rt<<1].pre1==mid-l+1)        stree[rt].pre1=stree[rt<<1].pre1+stree[rt<<1|1].pre1;    else stree[rt].pre1=stree[rt<<1].pre1;    if(stree[rt<<1|1].suf0==r-mid)        stree[rt].suf0=stree[rt<<1].suf0+stree[rt<<1|1].suf0;    else stree[rt].suf0=stree[rt<<1|1].suf0;    if(stree[rt<<1|1].suf1==r-mid)        stree[rt].suf1=stree[rt<<1].suf1+stree[rt<<1|1].suf1;    else stree[rt].suf1=stree[rt<<1|1].suf1;}void pushdown(int l, int r, int rt){    int mid=(l+r)>>1;    if(stree[rt].set0)    {        stree[rt].set0=0;        stree[rt<<1].flip=stree[rt<<1].set1=0;stree[rt<<1].set0=1;        stree[rt<<1].num0=mid-l+1;stree[rt<<1].num1=0;        stree[rt<<1].pre0=stree[rt<<1].suf0=stree[rt<<1].ma0=mid-l+1;        stree[rt<<1].pre1=stree[rt<<1].suf1=stree[rt<<1].ma1=0;        stree[rt<<1|1].flip=stree[rt<<1|1].set1=0;stree[rt<<1|1].set0=1;        stree[rt<<1|1].num0=r-mid;stree[rt<<1|1].num1=0;        stree[rt<<1|1].pre0=stree[rt<<1|1].suf0=stree[rt<<1|1].ma0=r-mid;        stree[rt<<1|1].pre1=stree[rt<<1|1].suf1=stree[rt<<1|1].ma1=0;    }    else if(stree[rt].set1)    {        stree[rt].set1=0;        stree[rt<<1].flip=stree[rt<<1].set0=0;stree[rt<<1].set1=1;        stree[rt<<1].num1=mid-l+1;stree[rt<<1].num0=0;        stree[rt<<1].pre1=stree[rt<<1].suf1=stree[rt<<1].ma1=mid-l+1;        stree[rt<<1].pre0=stree[rt<<1].suf0=stree[rt<<1].ma0=0;        stree[rt<<1|1].flip=stree[rt<<1|1].set0=0;stree[rt<<1|1].set1=1;        stree[rt<<1|1].num1=r-mid;stree[rt<<1|1].num0=0;        stree[rt<<1|1].pre1=stree[rt<<1|1].suf1=stree[rt<<1|1].ma1=r-mid;        stree[rt<<1|1].pre0=stree[rt<<1|1].suf0=stree[rt<<1|1].ma0=0;    }    else if(stree[rt].flip)    {        stree[rt].flip=0;        stree[rt<<1].flip^=1;        if(stree[rt<<1].set0) stree[rt<<1].set1=1, stree[rt<<1].set0=0, stree[rt<<1].flip=0;        else if(stree[rt<<1].set1) stree[rt<<1].set0=1, stree[rt<<1].set1=0, stree[rt<<1].flip=0;        swap(stree[rt<<1].ma0, stree[rt<<1].ma1);        swap(stree[rt<<1].num0, stree[rt<<1].num1);        swap(stree[rt<<1].pre0, stree[rt<<1].pre1);        swap(stree[rt<<1].suf0, stree[rt<<1].suf1);        stree[rt<<1|1].flip^=1;        if(stree[rt<<1|1].set0) stree[rt<<1|1].set1=1, stree[rt<<1|1].set0=0, stree[rt<<1|1].flip=0;        else if(stree[rt<<1|1].set1) stree[rt<<1|1].set0=1, stree[rt<<1|1].set1=0, stree[rt<<1|1].flip=0;        swap(stree[rt<<1|1].ma0, stree[rt<<1|1].ma1);        swap(stree[rt<<1|1].num0, stree[rt<<1|1].num1);        swap(stree[rt<<1|1].pre0, stree[rt<<1|1].pre1);        swap(stree[rt<<1|1].suf0, stree[rt<<1|1].suf1);    }}void build(int l, int r, int rt){    stree[rt].init();    if(l==r)    {        if(num[l]) stree[rt].num1=stree[rt].pre1=stree[rt].suf1=stree[rt].ma1=1;        else stree[rt].num0=stree[rt].pre0=stree[rt].suf0=stree[rt].ma0=1;        return;    }    int mid=(l+r)>>1;    build(lson), build(rson);    pushup(l, r, rt);}void update(int L, int R, int k, int l, int r, int rt){    if(L<=l&&r<=R)    {        if(k==0)//set0        {            if(stree[rt].set0) return;            else            {                stree[rt].set1=stree[rt].flip=0;stree[rt].set0=1;                stree[rt].num0=stree[rt].pre0=stree[rt].suf0=stree[rt].ma0=r-l+1;                stree[rt].num1=stree[rt].pre1=stree[rt].suf1=stree[rt].ma1=0;            }        }        else if(k==1)//set1        {            if(stree[rt].set1) return;            else            {                stree[rt].set0=stree[rt].flip=0;stree[rt].set1=1;                stree[rt].num0=stree[rt].pre0=stree[rt].suf0=stree[rt].ma0=0;                stree[rt].num1=stree[rt].pre1=stree[rt].suf1=stree[rt].ma1=r-l+1;            }        }        else if(k==2)//flip        {            if(stree[rt].set0) stree[rt].set0=0, stree[rt].set1=1, stree[rt].flip=0;            else if(stree[rt].set1) stree[rt].set0=1, stree[rt].set1=0, stree[rt].flip=0;            else stree[rt].flip^=1;            swap(stree[rt].ma0, stree[rt].ma1);            swap(stree[rt].num0, stree[rt].num1);            swap(stree[rt].pre0, stree[rt].pre1);            swap(stree[rt].suf0, stree[rt].suf1);        }        return;    }    pushdown(l, r, rt);    int mid=(l+r)>>1;    if(L<=mid) update(L, R, k, lson);    if(R>mid) update(L, R, k, rson);    pushup(l, r, rt);}int query1(int L, int R, int l, int r, int rt){    if(L<=l&&r<=R) return stree[rt].num1;    pushdown(l, r, rt);    int mid=(l+r)>>1;    int sum=0;    if(L<=mid) sum+=query1(L, R, lson);    if(mid<R) sum+=query1(L, R, rson);    return sum;}Stree query2(int L, int R, int l, int r, int rt){    if(L<=l&&r<=R) return stree[rt];    pushdown(l, r, rt);    int mid=(l+r)>>1;    Stree ll, rr;ll.init(), rr.init();    if(L<=mid) ll=query2(L, R, lson);    if(mid<R) rr=query2(L, R, rson);    Stree res;res.init();    res.ma1=max3(ll.ma1, rr.ma1, ll.suf1+rr.pre1);    if(ll.pre1==mid-l+1)        res.pre1=ll.pre1+rr.pre1;    else res.pre1=ll.pre1;    if(rr.suf1==r-mid)        res.suf1=ll.suf1+rr.suf1;    else res.suf1=rr.suf1;    return res;}int main(){    int n, m;scanf("%d%d", &n, &m);    for(int i=1;i<=n;i++) scanf("%d", &num[i]);    build(1, n, 1);    for(int i=1;i<=m;i++)    {        int op, x, y;scanf("%d%d%d", &op, &x, &y);x++, y++;        if(op==0)            update(x, y, 0, 1, n, 1);        else if(op==1)            update(x, y, 1, 1, n, 1);        else if(op==2)            update(x, y, 2, 1, n, 1);        else if(op==3)            printf("%d\n", query1(x, y, 1, n, 1));        else if(op==4)            printf("%d\n", query2(x, y, 1, n, 1).ma1);    }    //system("pause");    return 0;}