• 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));
            }
        }
    }
  • 相关阅读:
    C#编码标准--编码习惯
    课程九,课堂测试
    JAVAweb 分级测试
    第八周 课堂报告
    javaweb界面
    12月9日,第一次自查报告
    课程管理系统后台JAVA代码
    《程序员修炼之道+从小工到专家》读后有感
    12月9日 自查后续
    课程管理系统JAVAweb前端代码
  • 原文地址:https://www.cnblogs.com/sweat123/p/4673254.html
Copyright © 2020-2023  润新知