hdu3397 线段树 成段更新

这题真的呵呵了。敲了很长时间,调了很多bug,把0 1 输出,解决了。最后想取反,怎么搞都有bug,

最后还是看了大牛们的博客。不过这题真的敲得爽,调bug时基本把线段树过程全部弄了一遍。

#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));
        }
    }
}
原文地址:https://www.cnblogs.com/sweat123/p/4673254.html