hdu 3397セグメントツリーセグメント更新

19214 ワード

この問題は本当にほほほとした.長い間叩いて、バグをたくさん調整して、0 1を出力して、解決しました.最後に逆を取ろうとすると、どうやってもバグがあり、
最後に大牛たちのブログを見ました.しかし、この問題は本当にさっぱりしていて、バグを調整するときに基本的に線分の木の過程を全部しました.
#include<stdio.h>

#include<string.h>

#define lson l,m,rt<<1

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

#define maxn 100010

int mark[maxn<<2];// 

int rsum[maxn<<2],lsum[maxn<<2],msum[maxn<<2];// 1

int numone[maxn<<2];// 1 

int num[maxn<<2];// 

int max(int x,int y)

{

    return x>y?x:y;

}

int min(int x,int y)

{

    return x<y?x:y;

}



void pushup(int l,int r,int rt)

{

    int len=r-l+1;

    int m=(l+r)/2;

    if(mark[rt<<1]==mark[rt<<1|1])

        mark[rt]=mark[rt<<1];// mark

    else mark[rt]=-1;

    

    if(mark[rt]==1)

    {

        msum[rt]=lsum[rt]=rsum[rt]=numone[rt]=len;// mark 1, 

    }

    else if(mark[rt]==0)

    {

        numone[rt]=lsum[rt]=msum[rt]=rsum[rt]=0;// 

    }

    else// mark -1

    {

        lsum[rt]=lsum[rt<<1];

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

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

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

        if(lsum[rt<<1]==m-l+1)lsum[rt]=lsum[rt<<1]+lsum[rt<<1|1];

        if(rsum[rt<<1|1]==r-m)rsum[rt]=rsum[rt<<1|1]+rsum[rt<<1];

        msum[rt]=max(msum[rt],lsum[rt<<1|1]+rsum[rt<<1]);

    }

}



void pushdown(int l,int r,int rt)

{

    

    if(mark[rt]!=-1)

    {

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

        if(mark[rt]==1)

        {

            int len=r-l+1;

            numone[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=msum[rt<<1]=len-len/2;

            numone[rt<<1|1]=lsum[rt<<1|1]=rsum[rt<<1|1]=msum[rt<<1|1]=len/2;

        }

        else

        {

            lsum[rt<<1]=rsum[rt<<1]=msum[rt<<1]=numone[rt<<1]=0;

            lsum[rt<<1|1]=rsum[rt<<1|1]=msum[rt<<1|1]=numone[rt<<1|1]=0;

        }

        mark[rt]=-1;

    }

}



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

{

    if(l==r)

    {

        numone[rt]=lsum[rt]=rsum[rt]=msum[rt]=mark[rt]=num[l];

        return;

    }

    int m=(l+r)/2;

    build(lson);

    build(rson);

    pushup(l,r,rt);

}

void updata(int L,int R,int c,int l,int r,int rt)// 0   1 

{

    if(l>=L&&R>=r)

    {

        mark[rt]=c;

        if(c==0)

        {

            lsum[rt]=rsum[rt]=msum[rt]=0;

            numone[rt]=0;

        }

        else if(c==1)

        {

            lsum[rt]=rsum[rt]=msum[rt]=r-l+1;

            numone[rt]=r-l+1;

        }

        return ;

    }

    pushdown(l,r,rt);

    int m=(l+r)/2;

    if(m>=L)

        updata(L,R,c,lson);

    if(R>m)

        updata(L,R,c,rson);

    pushup(l,r,rt);

}



void change(int L,int R,int l,int r,int rt)// 

{

    if(l>=L&&R>=r&&mark[rt]!=-1)

    {

        if(mark[rt]==1)

            lsum[rt]=msum[rt]=rsum[rt]=numone[rt]=0;

        else if(mark[rt]==0)

            lsum[rt]=msum[rt]=rsum[rt]=numone[rt]=r-l+1;

        mark[rt]^=1;

        return;

    }

    pushdown(l,r,rt);

    int m=(l+r)/2;

    if(m>=L)

        change(L,R,lson);

    if(R>m)

        change(L,R,rson);

    pushup(l,r,rt);

}



int query(int L,int R,int l,int r,int rt)// 1 

{

    if(l>=L&&R>=r)

    {

        return numone[rt];

    }

    pushdown(l,r,rt);

    int ret=0;

    int m=(l+r)/2;

    if(m>=L)

        ret+=query(L,R,lson);

    if(R>m)

        ret+=query(L,R,rson);

    return ret;

}



int queryone(int L,int R,int l,int r,int rt)// 1 

{

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

    {

        return msum[rt];

    }

    pushdown(l,r,rt);

    int ret=-99999999;

    int m=(l+r)/2;

    if(m>=L)

        ret=max(ret,queryone(L,R,lson));

    if(R>m)

        ret=max(ret,queryone(L,R,rson)); 

    ret=max(ret,min(m-L+1,rsum[rt<<1])+min(R-m,lsum[rt<<1|1]));// 

    return ret;

}



int main()

{

    int i,n,m,t;

    scanf("%d",&t);

    while(t--)

    {

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

        

        for(i=1;i<=n;i++)

            scanf("%d",&num[i]);

    



        build(1,n,1);

        int x,y,z;

        

        while(m--)

        {

            scanf("%d%d%d",&x,&y,&z);

            if(x==0)

                updata(y+1,z+1,0,1,n,1);

            else if(x==1)

                updata(y+1,z+1,1,1,n,1);

            else if(x==2)

                change(y+1,z+1,1,n,1);

            else if(x==3)

                printf("%d
",query(y+1,z+1,1,n,1)); else if(x==4) printf("%d
",queryone(y+1,z+1,1,n,1)); } } }