[Scoi2010] Sequence Operations

Description

lxhgww recently received a 01 sequence, the sequence contains n numbers, these numbers are either 0 or 1, and now there are five transformation operations and query operations for this sequence:

0 ab turns all numbers in the interval [a, b] into 0

1 ab turns all numbers in the interval [a, b] into 1

2 ab Invert all numbers in the [a,b] interval, that is to say, turn all 0s into 1s, and turn all 1s into 0s

3 ab ask how many 1s are in the interval [a, b]

4 ab asks how many consecutive 1s are in the interval [a, b]

For every query operation, lxhgww needs to give an answer, smart programmers, can you help him?

Input

The first line of input data includes 2 numbers, n and m, which represent the length of the sequence and the number of operations, respectively. The second line includes n numbers, which represent the initial state of the sequence. Next m lines, each line has 3 numbers, op, a, b, (0 <= op <= 4, 0 <= a <= b)

Output

For each query operation, output a line, including 1 number, indicating its corresponding answer

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

For 30% of the data, 1<=n, m<=1000 For 100% of the data, 1<=n, m<=100000

Solution

I deeply feel the power of refactoring code.

Let's take a look at the question first, the feeling of a full line segment tree, how many 1's are easier to handle, a sum array can be solved, then continuous 1's can be easily found by difference. Then, flipping was added, which led to the continuous recording of 0s and the 0s on the right of the 0 on the left, resulting in a huge amount of code and a lot of details.

Let's talk about pushdown, then you can find that the level of the overlay mark is higher than that of the flip mark, because it becomes a number after being overwritten, no matter how you flip it in front of you, so when we change the overlay mark, we need to make it right and left. The flip mark is covered with a piece. So we also have to do the overwrite operation first and then flip, otherwise this operation is useless. . .

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstring>
#include<algorithm>
#define ls rt<<1
#define rs rt<<1|1
#define re register
#define maxn 500007
using namespace std;
int a[maxn<<2];
struct node {
    int l,r,t;
} qmax;
struct tree {
    int tag0[maxn<<2],tag1[maxn<<2],rev[maxn<<2],l0[maxn<<2],r0[maxn<<2],l1[maxn<<2],r1[maxn<<2],add[maxn<<2],v[maxn<<2];
    int tag[maxn<<2];
    void pushup(int l,int r,int rt) {
        int mid=l+r>>1;
        v[rt]=v[ls]+v[rs];
        if(l1[ls]==mid-l+1) l1[rt]=l1[ls]+l1[rs];else l1[rt]=l1[ls];
        if(r1[rs]==r-mid) r1[rt]=r1[rs]+r1[ls];else r1[rt]=r1[rs];
        if(l0[ls]==mid-l+1) l0[rt]=l0[ls]+l0[rs];else l0[rt]=l0[ls];
        if(r0[rs]==r-mid) r0[rt]=r0[rs]+r0[ls];else r0[rt]=r0[rs];
        tag1[rt]=max(max(tag1[ls],tag1[rs]),l1[rs]+r1[ls]);
        tag0[rt]=max(max(tag0[ls],tag0[rs]),r0[ls]+l0[rs]);
    }
    void pushdown(int l,int r,int rt) {
        int mid=l+r>>1;
        if(tag[rt]!=-1) {
            tag[ls]=tag[rs]=tag[rt];
            v[ls]=tag1[ls]=l1[ls]=r1[ls]=(mid-l+1)*tag[rt];
            v[rs]=tag1[rs]=r1[rs]=l1[rs]=(r-mid)*tag[rt];
            tag0[ls]=r0[ls]=l0[ls]=(mid-l+1)*(tag[rt]^1);
            tag0[rs]=r0[rs]=l0[rs]=(r-mid)*(tag[rt]^1);
            rev[ls]=rev[rs]=0;tag[rt]=-1;
        }
        if(rev[rt]==1) {
            rev[rt]=0;
            v[ls]=(mid-l+1)-v[ls];v[rs]=(r-mid)-v[rs];
            swap(tag0[ls],tag1[ls]);swap(tag0[rs],tag1[rs]);
            swap(l0[ls],l1[ls]);swap(l0[rs],l1[rs]);
            swap(r0[ls],r1[ls]);swap(r0[rs],r1[rs]);
            rev[ls]^=1;rev[rs]^=1;
        }
    }
    void build(int l,int r,int rt) {
        tag[rt]=-1;
        if(l==r) {
            v[rt]=l1[rt]=r1[rt]=tag1[rt]=a[l];
            l0[rt]=r0[rt]=tag0[rt]=(a[l]^1);
            return;
        }
        int mid=l+r>>1;
        build(l,mid,ls);
        build(mid+1,r,rs);
        pushup(l,r,rt);
    }
    void change1(int L,int R,int k,int l,int r,int rt) {
        if(L<=l&&r<=R) {
            int qu=r-l+1;
            v[rt]=tag1[rt]=r1[rt]=l1[rt]=qu*k;
            tag0[rt]=r0[rt]=l0[rt]=qu*(k^1);
            tag[rt]=k;rev[rt]=0;
            return;
        }
        pushdown(l,r,rt);
        int mid=l+r>>1;
        if(L<=mid) change1(L,R,k,l,mid,ls);
        if(mid<R) change1(L,R,k,mid+1,r,rs);
        pushup(l,r,rt);
    }
    void change2(int L,int R,int l,int r,int rt) {
        if(L<=l&&r<=R) {
            int qu=r-l+1;
            v[rt]=qu-v[rt];
            swap(tag1[rt],tag0[rt]);
            swap(l1[rt],l0[rt]);
            swap(r1[rt],r0[rt]);
            rev[rt]^=1;
            return;
        }
        pushdown(l,r,rt);
        int mid=l+r>>1;
        if(L<=mid) change2(L,R,l,mid,ls);
        if(R>mid) change2(L,R,mid+1,r,rs);
        pushup(l,r,rt);
    }
    int ask1(int L,int R,int l,int r,int rt) {
        if(L<=l&&r<=R) return v[rt];
        pushdown(l,r,rt);
        if(l>R||r<L) return 0;
        int mid=l+r>>1;
        return ask1(L,R,l,mid,ls)+ask1(L,R,mid+1,r,rs);
    }
    node ask2(int L,int R,int l,int r,int rt) {
        if(L<=l&&r<=R) return(node) {
            l1[rt],r1[rt],tag1[rt]
        };
        pushdown(l,r,rt);
        node t,tl,tr;
        int fll=0,flr=0;
        int mid=l+r>>1;
        if(L<=mid) tl=ask2(L,R,l,mid,ls);
        else tl=(node) {0,0,0},fll=1;
        if(R>mid) tr=ask2(L,R,mid+1,r,rs);
        else tr=(node) {0,0,0},flr=1;
        if(tl.l==mid-l+1) t.l=tl.l+tr.l;
        else if(fll==1) t.l=tr.l;
        else t.l=tl.l;
        if(tr.r==r-mid) t.r=tr.r+tl.r;
        else if(flr==1) t.r=tl.r;
        else t.r=tr.r;
        t.t=max(max(tr.t,tl.t),tl.r+tr.l);
        return t;
    }
} T;
inline int read() {
    int x=0,c=1;
    char ch=' ';
    while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
    while(ch=='-')c*=-1,ch=getchar(); 
    while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
    return x*c;
}
int main() {
    int n,m;
    n=read();
    m=read();
    for(re int i=1; i<=n; i++)
        a[i]=read();
    T.build(1,n,1);
    for(re int i=1; i<=m; i++) {
//      for(re int j=1; j<=20; j++)
    //      cout<<T.l0[j]<<" "<<T.l1[j]<<" - "<<T.r0[j]<<" "<<T.r1[j]<<" - "<<T.tag0[j]<<" "<<T.tag1[j]<<" - "<<T.rev[j]<<" - "<<T.tag[j]<<" - "<<T.v[j]<<endl;
        int flag,x,y;
        flag=read();x=read();y=read();x++;y++;
        if(flag==0||flag==1) T.change1(x,y,flag,1,n,1);
        if(flag==2) T.change2(x,y,1,n,1);
        if(flag==3) printf("%d\n",T.ask1(x,y,1,n,1));
        if(flag==4) printf("%d\n",T.ask2(x,y,1,n,1).t);
    }
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326491409&siteId=291194637