zoukankan      html  css  js  c++  java
  • P2572 [SCOI2010]序列操作

    建树的函数不要忘了return!!!

    
    #include<iostream>
    #include<cstdio>
    #define N 100005
    using namespace std;
    int n,m; 
    struct seg
    {
        int l,r;
        int l0,l1;//从左端开始连续0(1)的个数 
    	int r0,r1;//从右端开始连续0(1)的个数 
    	int mx0,mx1;//最多有多少个连续的0(1) 
    	int sum0,sum1;//有多少个0(1) 
        int rev;//取反标志 
    	int c; // 染色 
    	int full;//整个区间填充是1还是0 
    }t[N<<2];//共13个成员 
        
    void rev(int k)//第k个点取反 ,在外层修改了取反标志 
    {
        swap(t[k].l0,t[k].l1);
        swap(t[k].r0,t[k].r1);
        swap(t[k].mx0,t[k].mx1);
        swap(t[k].sum0,t[k].sum1);
        if(t[k].full!=-1)t[k].full^=1;
    }
    
    void color(int k,int v)//第k个点全改成0(1)  
    {
        t[k].rev=0;
        int s=t[k].r-t[k].l+1;
        if(v==0)
        {
           t[k].sum0=t[k].l0=t[k].r0=t[k].mx0=s;
           t[k].sum1=t[k].l1=t[k].r1=t[k].mx1=0;
        }
        else
        {
           t[k].sum0=t[k].l0=t[k].r0=t[k].mx0=0;
           t[k].sum1=t[k].l1=t[k].r1=t[k].mx1=s;
        }
        t[k].full=v;
    }
     
    seg merge(seg a,seg b) //合并子节点更新父节点所有成员 ,返回结构体 
    {
        seg tmp;
    	tmp.l=a.l;tmp.r=b.r;//左右端点 
        tmp.rev=0;tmp.c=-1;
        tmp.l0=a.l0;tmp.l1=a.l1;
        tmp.r0=b.r0;tmp.r1=b.r1;
        
        tmp.mx0=max(a.mx0,b.mx0);//3个取最大 
        tmp.mx1=max(a.mx1,b.mx1);
        tmp.mx0=max(tmp.mx0,a.r0+b.l0);
        tmp.mx1=max(tmp.mx1,a.r1+b.l1);
        
        tmp.sum0=a.sum0+b.sum0;
        tmp.sum1=a.sum1+b.sum1;
        
        if(a.full==0)tmp.l0=a.mx0+b.l0;
        else if(a.full==1)tmp.l1=a.mx1+b.l1;
        if(b.full==0)tmp.r0=b.mx0+a.r0;
        else if(b.full==1)tmp.r1=b.mx1+a.r1;
        //修改成员full 
        if(a.full==b.full)
           tmp.full=a.full;
        else tmp.full=-1;
        
        return tmp;
    }
    
    void pushup(int k)//利用子节点更新父节点 
    {
        t[k]=merge(t[k<<1],t[k<<1|1]);
    }
    
    //下传有什么用 。把父节点的信息下传给子节点 
    void pushdown(int k)
    {
        if(t[k].l==t[k].r)return;
        if(t[k].c!=-1)
        {
            t[k<<1].c=t[k<<1|1].c=t[k].c;
            color(k<<1,t[k].c);color(k<<1|1,t[k].c);
            t[k].c=-1;//??? 
        }
        if(t[k].rev)
        {
            t[k<<1].rev^=1;
            t[k<<1|1].rev^=1;
            rev(k<<1);rev(k<<1|1);
            t[k].rev=0;
        }
    }
    void build(int k,int l,int r)
    {
        t[k].l=l;t[k].r=r;
        t[k].c=-1;
        if(l==r)
        {
            scanf("%d",&t[k].full);//001 
            if(t[k].full)
            {t[k].l1=t[k].r1=t[k].mx1=t[k].sum1=1;}
            else
            {t[k].l0=t[k].r0=t[k].mx0=t[k].sum0=1;}
            return;
        }
        int mid=(l+r)>>1;
        build(k<<1,l,mid);
    	build(k<<1|1,mid+1,r);
        pushup(k);//更新父节点 
    }
    
    //修改一个区间的值时,要先向下更新子节点,再向上更新父节点  
    void change(int k,int x,int y,int v)
    {
        pushdown(k);//先更新子节点 
        int l=t[k].l,r=t[k].r;
        if(l==x&&r==y)
        {
            color(k,v);
            t[k].c=v;
            return;
        }
        int mid=(l+r)>>1;
        if(mid>=y)change(k<<1,x,y,v);
        else if(mid<x)change(k<<1|1,x,y,v);
        else
        {
            change(k<<1,x,mid,v);
            change(k<<1|1,mid+1,y,v);
        }
        pushup(k);//更新父节点 
    }
    
    //修改一个区间,全取反 ,要先向下更新子节点,再向上更新父节点   
    void rever(int k,int x,int y)
    {
        pushdown(k);
        int l=t[k].l,r=t[k].r;
        if(l==x&&r==y)
        {
            rev(k);
            t[k].rev=1;
            return;
        }
        int mid=(l+r)>>1;
        if(mid>=y)rever(k<<1,x,y);
        else if(mid<x)rever(k<<1|1,x,y);
        else
        {
            rever(k<<1,x,mid);
            rever(k<<1|1,mid+1,y);
        }
        pushup(k);
    }
    
    //查询区间内最大有多少连续的1 ,因为要用到子节点的信息,所以先向下更新,没有更新子节点的信息,所以不用向上更新 
    seg ask(int k,int x,int y)
    {
        pushdown(k);
        int l=t[k].l,r=t[k].r;
        if(l==x&&y==r)return t[k];
        int mid=(l+r)>>1;
        if(mid>=y)return ask(k<<1,x,y);
        else if(mid<x)return ask(k<<1|1,x,y);
        else return merge(ask(k<<1,x,mid),ask(k<<1|1,mid+1,y));
    }
    
    //统计区间内1的总数 
    int asksum(int k,int x,int y)
    {
        pushdown(k);
        int l=t[k].l,r=t[k].r;
        if(l==x&&y==r)return t[k].sum1;//为什么不是落在区间内 
        int mid=(l+r)>>1;
        if(mid>=y)return asksum(k<<1,x,y);
        else if(mid<x)return asksum(k<<1|1,x,y);
        else return asksum(k<<1,x,mid)+asksum(k<<1|1,mid+1,y);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        build(1,1,n);
        for(int i=1;i<=m;i++)
        {
            int f,x,y;
            scanf("%d%d%d",&f,&x,&y);
            x++;y++; 
            switch(f)
            {
                case 0:change(1,x,y,0);break;
                case 1:change(1,x,y,1);break;
                case 2:rever(1,x,y);break;
                case 3:printf("%d
    ",asksum(1,x,y));break;
                case 4:printf("%d
    ",ask(1,x,y).mx1);break;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Mysql登录错误:ERROR 1045 (28000): Plugin caching_sha2_password could not be loaded
    Docker配置LNMP环境
    Docker安装mysqli扩展和gd扩展
    Docker常用命令
    Ubuntu常用命令
    单例模式的优缺点和使用场景
    ABP 多租户数据共享
    ABP Core 后台Angular+Ng-Zorro 图片上传
    ERROR Error: If ngModel is used within a form tag, either the name attribute must be set or the form control must be defined as 'standalone' in ngModelOptions.
    AbpCore 执行迁移文件生成数据库报错 Could not find root folder of the web project!
  • 原文地址:https://www.cnblogs.com/ShineEternal/p/11377059.html
Copyright © 2011-2022 走看看