hdu 3397 Sequence operation(很有意思的线段树题)

Sequence operation

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4952    Accepted Submission(s): 1452

Problem Description
lxhgww got a sequence contains n characters which are all '0's or '1's.
We have five operations here:
Change operations:
0 a b change all characters into '0's in [a , b]
1 a b change all characters into '1's in [a , b]
2 a b change all '0's into '1's and change all '1's into '0's in [a, b]
Output operations:
3 a b output the number of '1's in [a, b]
4 a b output the length of the longest continuous '1' string in [a , b]
 

 

Input
T(T<=10) in the first line is the case number.
Each case has two integers in the first line: n and m (1 <= n , m <= 100000).
The next line contains n characters, '0' or '1' separated by spaces.
Then m lines are the operations:
op a b: 0 <= op <= 4 , 0 <= a <= b < n.
 

 

Output
For each output operation , output the result.
 

 

Sample Input
1 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
 

 

Author
lxhgww&&shǎ崽
 

 

Source
 

 

Recommend
lcy
  题意:
给你一个0,1数组。你可以对数组进行以下操作。
0 x y   把[x,y]之间的元素置为0。
1 x y   把[x,y]之间的元素置为1。
2 x y   把[x,y]之间的元素置为1变成0,0变成1。
3 x y   求[x,y]之间元素1的个数。
4 x y   [x,y]之间最长连续1的长度。
思路:
对于0,1,3,4操作都很传统。区间更新区间统计。但是由于多了2操作所以就要多维护关于0的信息。这样进行2操作的时候之间交换1和0的信息就行了。还有查询的时候也有注意的地方。开始没注意那个地方导致wa数次。反复检查冗长的代码无数次。。。。可怜我的时间呀。。。哎。。。。。
详细见代码:
#include<algorithm>

#include<iostream>

#include<string.h>

#include<sstream>

#include<stdio.h>

#include<math.h>

#include<vector>

#include<string>

#include<queue>

#include<set>

#include<map>

using namespace std;

const int INF=0x3f3f3f3f;

const int maxn=100100;

int sta[maxn<<2],ml0[maxn<<2],mr0[maxn<<2],ml1[maxn<<2];//sta为标记。ml1为1左端连续。ml0为0左端连续

int mr1[maxn<<2],ma1[maxn<<2],ma0[maxn<<2],one[maxn<<2];//ma1为最大1连续数.one记录1的个数

void opp(int L,int R,int k)//对于2操作。0和1互换

{

    swap(ma0[k],ma1[k]);

    swap(ml0[k],ml1[k]);

    swap(mr0[k],mr1[k]);

    one[k]=R-L-one[k]+1;

}

void pushup(int L,int R,int k)//下传标记

{

    int ls,rs,mid;

    ls=k<<1;

    rs=ls|1;

    mid=(L+R)>>1;

    ml0[k]=ml0[ls];

    mr0[k]=mr0[rs];

    ml1[k]=ml1[ls];

    mr1[k]=mr1[rs];

    if(ml0[ls]==mid-L+1)

        ml0[k]+=ml0[rs];

    if(mr0[rs]==R-mid)

        mr0[k]+=mr0[ls];

    if(ml1[ls]==mid-L+1)

        ml1[k]+=ml1[rs];

    if(mr1[rs]==R-mid)

        mr1[k]+=mr1[ls];

    ma1[k]=max(ma1[ls],ma1[rs]);

    ma1[k]=max(ma1[k],mr1[ls]+ml1[rs]);

    ma0[k]=max(ma0[ls],ma0[rs]);

    ma0[k]=max(ma0[k],mr0[ls]+ml0[rs]);

    one[k]=one[ls]+one[rs];

}

void pushdown(int L,int R,int k)//上传

{

    int ls,rs,mid;

    ls=k<<1;

    rs=ls|1;

    mid=(L+R)>>1;

    //printf("mark %d->%d and %d->%d %d\n",L,mid,mid+1,R,sta[k]);

    if(sta[k]==0)

    {

        sta[ls]=sta[rs]=0;

        ma0[ls]=ml0[ls]=mr0[ls]=mid-L+1;

        ma1[ls]=ml1[ls]=mr1[ls]=one[ls]=ma1[rs]=ml1[rs]=mr1[rs]=one[rs]=0;

        ma0[rs]=ml0[rs]=mr0[rs]=R-mid;



    }

    else if(sta[k]==1)

    {

        sta[ls]=sta[rs]=1;

        ma0[ls]=ml0[ls]=mr0[ls]=ma0[rs]=ml0[rs]=mr0[rs]=0;

        ma1[ls]=ml1[ls]=mr1[ls]=one[ls]=mid-L+1;

        ma1[rs]=ml1[rs]=mr1[rs]=one[rs]=R-mid;

    }

    else

    {

        if(sta[ls]!=-1)//2操作对于0,1标记直接0,1标记互换

        {

            if(sta[ls]==2)//原先有2直接变-1

                sta[ls]=-1;

            else

                sta[ls]^=1;

        }

        else

            sta[ls]=2;

        if(sta[rs]!=-1)

        {

            if(sta[rs]==2)

                sta[rs]=-1;

            else

                sta[rs]^=1;

        }

        else

            sta[rs]=2;

        opp(L,mid,ls);

        opp(mid+1,R,rs);

    }

    sta[k]=-1;

}

void btree(int L,int R,int k)

{

    int ls,rs,mid;

    sta[k]=-1;

    if(L==R)

    {

        scanf("%d",&one[k]);

        if(one[k])

        {

            ma1[k]=ml1[k]=mr1[k]=1;

            ma0[k]=ml0[k]=mr0[k]=0;

        }

        else

        {

             ma1[k]=ml1[k]=mr1[k]=0;

             ma0[k]=ml0[k]=mr0[k]=1;

        }

        return ;

    }

    ls=k<<1;

    rs=ls|1;

    mid=(L+R)>>1;

    btree(L,mid,ls);

    btree(mid+1,R,rs);

    pushup(L,R,k);

    //printf("%d->%d\n",L,R);

    //printf("%d---%d----%d\n",ml1[k],mr1[k],one[k]);

}

void update(int L,int R,int l,int r,int k,int op)

{

    int ls,rs,mid;

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

    {

        if(op==0)

        {

            sta[k]=0;

            ma0[k]=ml0[k]=mr0[k]=R-L+1;

            ma1[k]=ml1[k]=mr1[k]=one[k]=0;

        }

        else if(op==1)

        {

            sta[k]=1;

            ma0[k]=ml0[k]=mr0[k]=0;

            ma1[k]=ml1[k]=mr1[k]=one[k]=R-L+1;

        }

        else

        {

            if(sta[k]==-1)

                sta[k]=2;

            else if(sta[k]==2)

                sta[k]=-1;

            else

                sta[k]^=1;

            opp(L,R,k);

        }

        //printf("mark %d->%d %d\n",L,R,op);

        //printf("%d->%d\n",L,R);

        //printf("%d---%d----%d\n",ml1[k],mr1[k],one[k]);

        return ;

    }

    if(sta[k]!=-1)

        pushdown(L,R,k);

    ls=k<<1;

    rs=ls|1;

    mid=(L+R)>>1;

    if(l>mid)

        update(mid+1,R,l,r,rs,op);

    else if(r<=mid)

        update(L,mid,l,r,ls,op);

    else

    {

        update(L,mid,l,mid,ls,op);

        update(mid+1,R,mid+1,r,rs,op);

    }

    pushup(L,R,k);

    //printf("%d->%d\n",L,R);

    //printf("%d---%d----%d\n",ml1[k],mr1[k],one[k]);

}

int qu(int L,int R,int l,int r,int k,int op)

{

    int ls,rs,mid,tmp,ll,rr;

    if(sta[k]==0)

        return 0;

    if(sta[k]==1)

        return r-l+1;

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

    {

        if(op==3)

            return one[k];

        else

            return ma1[k];

    }

    if(sta[k]!=-1)

        pushdown(L,R,k);

    ls=k<<1;

    rs=ls|1;

    mid=(L+R)>>1;

    if(l>mid)

        return qu(mid+1,R,l,r,rs,op);

    else if(r<=mid)

        return qu(L,mid,l,r,ls,op);

    else

    {

        if(op==3)

            return qu(L,mid,l,mid,ls,op)+qu(mid+1,R,mid+1,r,rs,op);

        else//4对于分离操作尤其注意!!最大值只能是以下几种情况。

        {

            tmp=max(qu(L,mid,l,mid,ls,op),qu(mid+1,R,mid+1,r,rs,op));//最大值在左儿子或右儿子中

            ll=max(mid-mr1[ls]+1,l);//最大值在中间区域

            rr=min(mid+ml1[rs],r);//注意范围

            tmp=max(tmp,rr-ll+1);

            return tmp;

        }

    }



}

int main()

{

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



    scanf("%d",&t);

    while(t--)

    {

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

        btree(1,n,1);

        while(m--)

        {

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

            a++,b++;

            if(op<3)

                update(1,n,a,b,1,op);

            else

                printf("%d\n",qu(1,n,a,b,1,op));

        }

    }

    return 0;

}



 

你可能感兴趣的:(sequence)