hdu 3397 Sequence operation 线段树

这道题关键是有两个延迟标记

当区间被完全覆盖时,要撤销抑或操作

所以每次先判断当前区间有没有被完全覆盖

有的话就直接改变相应的值,没有的话在判断有无异或标记

主要是这个地方要注意,其他地方都和另外一道题一样

代码有点长,但是不难

View Code
#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

const int maxn = 100010;

#define lson l,m,rt<<1

#define rson m+1,r,rt<<1|1

int num0[maxn<<2],num1[maxn<<2];

int lb0[maxn<<2],lb1[maxn<<2];

int rb0[maxn<<2],rb1[maxn<<2];

int mx1[maxn<<2],mx0[maxn<<2];

int col[maxn<<2];

int xor[maxn<<2];

int num;

int max(int a,int b){

    return a>b?a:b;

}

int min(int a,int b){

    return a<b?a:b;

}

void pushup(int rt,int m)

{

    lb0[rt]=lb0[rt<<1];rb0[rt]=rb0[rt<<1|1];

    if(lb0[rt]==m-(m>>1)) lb0[rt]+=lb0[rt<<1|1];

    if(rb0[rt]==(m>>1))  rb0[rt]+=rb0[rt<<1];

    

    lb1[rt]=lb1[rt<<1];rb1[rt]=rb1[rt<<1|1];

    if(lb1[rt]==m-(m>>1)) lb1[rt]+=lb1[rt<<1|1];

    if(rb1[rt]==(m>>1))  rb1[rt]+=rb1[rt<<1];

    

    num0[rt]=num0[rt<<1]+num0[rt<<1|1];

    num1[rt]=num1[rt<<1]+num1[rt<<1|1];

    

    mx1[rt]=max(mx1[rt<<1],mx1[rt<<1|1]);

    mx1[rt]=max(mx1[rt],rb1[rt<<1]+lb1[rt<<1|1]);

    

    mx0[rt]=max(mx0[rt<<1],mx0[rt<<1|1]);

    mx0[rt]=max(mx0[rt],rb0[rt<<1]+lb0[rt<<1|1]);

}

void build(int l,int r,int rt){

    col[rt]=-1; xor[rt]=0;

    if(l==r){

        scanf("%d",&num);

        num0[rt]=lb0[rt]=rb0[rt]=mx0[rt]=(num?0:1);

        num1[rt]=lb1[rt]=rb1[rt]=mx1[rt]=(num?1:0);

        return ;

    }

    int m=(l+r)>>1;

    build(lson);

    build(rson);

    pushup(rt,r-l+1);

}

void init(int rt,int m,int cmd){

   lb0[rt]=rb0[rt]=mx0[rt]=num0[rt]=m*(1-cmd);

   lb1[rt]=rb1[rt]=mx1[rt]=num1[rt]=m*cmd;

}

void change(int rt){

    swap(lb0[rt],lb1[rt]);

    swap(rb0[rt],rb1[rt]);

    swap(mx0[rt],mx1[rt]);

    swap(num0[rt],num1[rt]);

}

void pushdown(int rt,int m){

    if(col[rt]!=-1){

         col[rt<<1]=col[rt<<1|1]=col[rt];

         xor[rt<<1]=xor[rt<<1|1]=0;

         init(rt<<1,m-(m>>1),col[rt]);

         init(rt<<1|1,(m>>1),col[rt]);

         col[rt]=-1;

    }

    else if(xor[rt]){

        if(col[rt<<1]!=-1){

            col[rt<<1]^=1;

            init(rt<<1,m-(m>>1),col[rt<<1]);

        }

        else {

            xor[rt<<1]^=1;

            change(rt<<1);

        }

        if(col[rt<<1|1]!=-1){

            col[rt<<1|1]^=1;

            init(rt<<1|1,(m>>1),col[rt<<1|1]);

        }

        else {

            xor[rt<<1|1]^=1;

            change(rt<<1|1);

        }

        xor[rt]=0;

    }

}

void update(int L,int R,int cmd,int l,int r,int rt){

    if(L<=l&&r<=R){

        if(cmd<=1){

            xor[rt]=0;//取消异或标记

            col[rt]=cmd;//真个区间被完全覆盖为cmd

            init(rt,r-l+1,cmd);

        }

        else {

            if(col[rt]!=-1){//被完全覆盖,全是0或者全是1,相当于取反

                col[rt]^=1;

                init(rt,r-l+1,col[rt]);

            }

            else {

                xor[rt]^=1;

                change(rt);

            }

        }

        return ;

    }

    pushdown(rt,r-l+1);

    int m=(l+r)>>1;

    if(L<=m) update(L,R,cmd,lson);

    if(R>m) update(L,R,cmd,rson);

    pushup(rt,r-l+1);

}

int query1(int L,int R,int l,int r,int rt){

    if(L<=l&&r<=R)  return num1[rt];

    pushdown(rt,r-l+1);

    int m=(l+r)>>1;

    int ans=0;

    if(L<=m) ans+=query1(L,R,lson);

    if(R>m) ans+=query1(L,R,rson);

    return ans;

}

int  query2(int L,int R,int l,int r,int rt){

    if(L<=l&&r<=R) {

        return mx1[rt];

    }

    pushdown(rt,r-l+1);

    int m=(l+r)>>1;

    if(R<=m) return query2(L,R,lson);

    if(L>m) return query2(L,R,rson);

    int a=query2(L,R,lson);

    int b=query2(L,R,rson);

    a=a>b?a:b;

    b=min(m-L+1,rb1[rt<<1])+min(R-m,lb1[rt<<1|1]);

    return a>b?a:b;

}

int main(){

    int t,n,m,op,a,b;

    scanf("%d",&t);

    while(t--){

        scanf("%d%d",&n,&m);

        build(0,n-1,1);

        while(m--){

            scanf("%d%d%d",&op,&a,&b);

            if(op<=2) update(a,b,op,0,n-1,1);

            else {

                if(op==3) printf("%d\n",query1(a,b,0,n-1,1));

                else printf("%d\n",query2(a,b,0,n-1,1));

            }

        }

    }

    return 0;

}

你可能感兴趣的:(sequence)