hdu3397 Sequence operation

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

这道题是前面线段树知识的综合题,也和之前有些不同,是个很好的训练题,做了很长时间啊,还需努力。这里的难点是异或运算,即把区间中的0变成1,1变成0.这里我维护每个区间的llen0,rlen0,tlen0,llen1,rlen1,tlen1,即区间从左端点起的向右最大连续0(1)区间长度,从右端起的最大向左连续0(1)区间长度,以及区间最大的连续0(1)区间长度,然后异或操作的时候,只要把0,1换一下,然后用pushup操作就可以了,再记录一个异或操作符x_or.

<pre name="code" class="cpp">#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
#define inf 0x7fffffff
#define maxn 100050
int a[maxn];
struct node{
    int l,r,yihuo,cnt;
    int llen0,rlen0,tlen0;
    int llen1,rlen1,tlen1;
    int num0,num1;
}b[4*maxn];

int num1,num2;

void pushdown(int i)
{
    if(b[i].l==b[i].r)return;
    if(b[i].cnt!=-1){
        b[i*2].cnt=b[i*2+1].cnt=b[i].cnt;
        b[i*2].yihuo=b[i*2+1].yihuo=0;
        if(b[i].cnt==0){
            b[i*2].llen0=b[i*2].rlen0=b[i*2].tlen0=b[i*2].r-b[i*2].l+1;
            b[i*2].llen1=b[i*2].rlen1=b[i*2].tlen1=0;
            b[i*2].num0=b[i*2].r-b[i*2].l+1;
            b[i*2].num1=0;

            b[i*2+1].llen0=b[i*2+1].rlen0=b[i*2+1].tlen0=b[i*2+1].r-b[i*2+1].l+1;
            b[i*2+1].llen1=b[i*2+1].rlen1=b[i*2+1].tlen1=0;
            b[i*2+1].num0=b[i*2+1].r-b[i*2+1].l+1;
            b[i*2+1].num1=0;


        }
        else if(b[i].cnt==1){
            b[i*2].llen0=b[i*2].rlen0=b[i*2].tlen0=0;
            b[i*2].llen1=b[i*2].rlen1=b[i*2].tlen1=b[i*2].r-b[i*2].l+1;
            b[i*2].num0=0;
            b[i*2].num1=b[i*2].r-b[i*2].l+1;

            b[i*2+1].llen0=b[i*2+1].rlen0=b[i*2+1].tlen0=0;
            b[i*2+1].llen1=b[i*2+1].rlen1=b[i*2+1].tlen1=b[i*2+1].r-b[i*2+1].l+1;
            b[i*2+1].num0=0;
            b[i*2+1].num1=b[i*2+1].r-b[i*2+1].l+1;


        }
        b[i].cnt=-1;
    }

    if(b[i].yihuo!=0){
        b[i*2].yihuo=1^b[i*2].yihuo;
        swap(b[i*2].llen0,b[i*2].llen1);
        swap(b[i*2].rlen0,b[i*2].rlen1);
        swap(b[i*2].tlen0,b[i*2].tlen1);
        swap(b[i*2].num0,b[i*2].num1);

        /*
        if(b[i*2].cnt!=-1){  这里和下面注释的不能写,因为如果换了的话就和父亲节点的信息不同了
            b[i*2].cnt^=1;
        }
        */



        b[i*2+1].yihuo=1^b[i*2+1].yihuo;
        swap(b[i*2+1].llen0,b[i*2+1].llen1);
        swap(b[i*2+1].rlen0,b[i*2+1].rlen1);
        swap(b[i*2+1].tlen0,b[i*2+1].tlen1);
        swap(b[i*2+1].num0,b[i*2+1].num1);

        /*
        if(b[i*2+1].cnt!=-1){
            b[i*2+1].cnt^=1;
        }
        */

        b[i].yihuo=0;
    }
}


void pushup(int i)
{
    if(b[i].l==b[i].r)return;
    b[i].num0=b[i*2].num0+b[i*2+1].num0;
    b[i].num1=b[i*2].num1+b[i*2+1].num1;
    b[i].llen0=b[i*2].llen0;
    b[i].rlen0=b[i*2+1].rlen0;
    if(b[i*2].llen0==b[i*2].r-b[i*2].l+1){
        b[i].llen0+=b[i*2+1].llen0;
    }
    if(b[i*2+1].rlen0==b[i*2+1].r-b[i*2+1].l+1){
        b[i].rlen0+=b[i*2].rlen0;
    }
    b[i].tlen0=max(b[i*2].tlen0,b[i*2+1].tlen0);
    b[i].tlen0=max(b[i*2].rlen0+b[i*2+1].llen0,b[i].tlen0);



    b[i].llen1=b[i*2].llen1;
    b[i].rlen1=b[i*2+1].rlen1;
    if(b[i*2].llen1==b[i*2].r-b[i*2].l+1){
        b[i].llen1+=b[i*2+1].llen1;
    }
    if(b[i*2+1].rlen1==b[i*2+1].r-b[i*2+1].l+1){
        b[i].rlen1+=b[i*2].rlen1;
    }
    b[i].tlen1=max(b[i*2].tlen1,b[i*2+1].tlen1);
    b[i].tlen1=max(b[i*2].rlen1+b[i*2+1].llen1,b[i].tlen1);



}


void build(int l,int r,int i)
{
    int mid;
    b[i].l=l;b[i].r=r;b[i].yihuo=0;b[i].cnt=-1;
    if(l==r){
        if(a[l]==0){
            b[i].llen0=b[i].rlen0=b[i].tlen0=1;
            b[i].llen1=b[i].rlen1=b[i].tlen1=0;
            b[i].num0=1;
            b[i].num1=0;
        }
        else{
            b[i].llen0=b[i].rlen0=b[i].tlen0=0;
            b[i].llen1=b[i].rlen1=b[i].tlen1=1;
            b[i].num0=0;
            b[i].num1=1;
        }
        return;
    }
    mid=(l+r)/2;
    build(l,mid,i*2);
    build(mid+1,r,i*2+1);
    pushup(i);
}


void update01(int l,int r,int num,int i)
{
    int mid;
    if(b[i].l==l && b[i].r==r){
        b[i].yihuo=0;
        b[i].cnt=num;
        if(num==0){
            b[i].llen0=b[i].rlen0=b[i].tlen0=b[i].r-b[i].l+1;
            b[i].llen1=b[i].rlen1=b[i].tlen1=0;
            b[i].num0=b[i].r-b[i].l+1;
            b[i].num1=0;
        }
        else{
            b[i].llen0=b[i].rlen0=b[i].tlen0=0;
            b[i].llen1=b[i].rlen1=b[i].tlen1=b[i].r-b[i].l+1;
            b[i].num0=0;
            b[i].num1=b[i].r-b[i].l+1;
        }
        return;
    }
    pushdown(i);
    mid=(b[i].l+b[i].r)/2;
    if(r<=mid)update01(l,r,num,i*2);
    else if(l>mid)update01(l,r,num,i*2+1);
    else{
        update01(l,mid,num,i*2);
        update01(mid+1,r,num,i*2+1);
    }
    pushup(i);

}

void update2(int l,int r,int i)
{
    int mid;
    if(b[i].l==l && b[i].r==r){
        b[i].yihuo=1^b[i].yihuo;
        swap(b[i].llen0,b[i].llen1);
        swap(b[i].rlen0,b[i].rlen1);
        swap(b[i].tlen0,b[i].tlen1);
        swap(b[i].num0,b[i].num1);
        //if(b[i].cnt!=-1)b[i].cnt^=1;这句不用写
        return;
    }
    pushdown(i);//pushdown(i)放上面下面都行的
    mid=(b[i].l+b[i].r)/2;
    if(r<=mid)update2(l,r,i*2);
    else if(l>mid)update2(l,r,i*2+1);
    else{
        update2(l,mid,i*2);
        update2(mid+1,r,i*2+1);
    }
    pushup(i);
}

void question1(int l,int r,int i)
{
    int mid;
    if(b[i].l==l && b[i].r==r){
        num1+=b[i].num1;
        return;
    }
    pushdown(i);
    mid=(b[i].l+b[i].r)/2;
    if(r<=mid)question1(l,r,i*2);
    else if(l>mid)question1(l,r,i*2+1);
    else{
        question1(l,mid,i*2);
        question1(mid+1,r,i*2+1);
    }


}
int question2(int l,int r,int i)
{
    int mid;
    if(b[i].l==l && b[i].r==r){
        return b[i].tlen1;
    }
    pushdown(i);
    mid=(b[i].l+b[i].r)/2;
    if(r<=mid){
        return question2(l,r,i*2);
    }
    else if(l>mid){
        return question2(l,r,i*2+1);
    }
    else{
        int l1,r1;
        l1=max(b[i*2].r-b[i*2].rlen1+1,l);
        r1=min(b[i*2+1].l+b[i*2+1].llen1-1,r);
        int temp=r1-l1+1;
        temp=max(temp,question2(l,mid,i*2) );
        temp=max(temp,question2(mid+1,r,i*2+1));
        return temp;
    }
}





int main()
{
    int n,m,i,j,T,f,c,d;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        build(1,n,1);
        for(i=1;i<=m;i++){
            scanf("%d%d%d",&f,&c,&d);
            c++;d++;
            if(f==0){
                update01(c,d,0,1);
            }
            if(f==1){
                update01(c,d,1,1);
            }
            else if(f==2){
                update2(c,d,1);
            }
            else if(f==3){
                num1=0;
                question1(c,d,1);
                printf("%d\n",num1);
            }
            else if(f==4){
                printf("%d\n",question2(c,d,1));
            }
        }
    }
    return 0;
}



 
 

你可能感兴趣的:(线段树)