• 高度模式化的线段树写法


    (水)

    struct point{int l,r,val1,val2/*要维护的信息*/,tag1,tag2/*标记*/;}tree[maxn<<2];
    point pushup(point x,point y,int tg1,int tg2/*标记传进来*/)
    {
        point ans;
        if(x.l==0)return y;//如果其中一个为空直接返回另一个
        if(y.l==0)return x;
        ans.l=x.l;ans.r=y.r;
        ans.tag1=tg1;ans.tag2=tg2;
        /*这里写信息的pushup*/
        return ans;
    }
    void pushup(int x)
    {
        int lson=x<<1,rson=lson|1;
        tree[x]=pushup(tree[lson],tree[rson],tree[x].tag1,tree[x].tag2);
    }
    void pushtag1(int x,int k)//有多个这样的函数,每个函数处理一个 tag
    {
        tree[x].tag=k;
        /*这里写对同结点其他标记的影响*/
        /*然后写对同结点要维护的值的影响*/
    }
    void pushdown(int x)
    {
        int lson=x<<1,rson=lson|1;
        if(tree[x].l==tree[x].r)return;
        if(tree[x].tag1!=0)
        {
            pushtag1(lson,tree[x].tag1);
            pushtag1(rson,tree[x].tag1);
            tree[x].tag1=0;
        }
    }
    void build(int x,int l,int r)
    {
        tree[x]=(point){l,r,0,0,0};//清零
        if(l==r)
        {
            /*要维护的信息的初始化*/
            return;
        }
        int mid=(tree[x].l+tree[x].r)>>1,lson=x<<1,rson=lson|1;
        build(lson,l,mid);build(rson,mid+1,r);
        pushup(x);
    }
    void modify_tag1(int x,int l,int r,int k)
    {
        pushdown(x);
        if(l<=tree[x].l&&r>=tree[x].r){pushtag1(x,k);return;}
        int mid=(tree[x].l+tree[x].r)>>1,lson=x<<1,rson=lson|1;
        if(l<=mid)modify_tag1(lson,l,r,k);
        if(r>mid)modify_tag1(rson,l,r,k);
        pushup(x);
    }
    point query_val1(int x,int l,int r)
    {
        pushdown(x);
        if(l<=tree[x].l&&r>=tree[x].r)return tree[x];
        int mid=(tree[x].l+tree[x].r)>>1,lson=x<<1,rson=lson|1;
        point ans=(point){0,0,0,0,0};
        if(l<=mid)ans=pushup(query_val1(lson,l,r),ans,-1,0);//这里最后传的是初始时的标记
        if(r>mid)ans=pushup(ans,query_val1(rson,l,r),-1,0);
        return ans;
    }
    

    这种模板的好处是查询的时候不用动脑子。
    然后你就能做这道题了!

    code:

    const int maxn=100010;
    int n,m,ans,cnt,a[maxn],p[maxn];
    struct point{int l,r,sum,maxcon[2],lcon[2],rcon[2],cover,flip;}tree[maxn<<2];
    //sum:区间内1的数量
    //maxcon[2]:区间内最多连续0/1的数量
    //lcon[2]:区间左端最多连续0/1的数量
    //rcon[2]:区间右端最多连续0/1的数量
    //cover:区间是否被覆盖(-1:未被覆盖,0/1:被覆盖为0/1)
    //flip:区间是否被全部取反
    point pushup(point x,point y,int cov,int flp)
    {
        point ans;
        if(x.l==0)return y;
        if(y.l==0)return x;
        ans.l=x.l;ans.r=y.r;
        ans.cover=cov;ans.flip=flp;
        ans.sum=x.sum+y.sum;
        ans.maxcon[0]=max(max(x.maxcon[0],y.maxcon[0]),x.rcon[0]+y.lcon[0]);
        ans.maxcon[1]=max(max(x.maxcon[1],y.maxcon[1]),x.rcon[1]+y.lcon[1]);
        if(x.sum==0)ans.lcon[0]=x.r-x.l+1+y.lcon[0];
        else ans.lcon[0]=x.lcon[0];
        if(x.sum==x.r-x.l+1)ans.lcon[1]=x.r-x.l+1+y.lcon[1];
        else ans.lcon[1]=x.lcon[1];
        if(y.sum==0)ans.rcon[0]=y.r-y.l+1+x.rcon[0];
        else ans.rcon[0]=y.rcon[0];
        if(y.sum==y.r-y.l+1)ans.rcon[1]=y.r-y.l+1+x.rcon[1];
        else ans.rcon[1]=y.rcon[1];
        return ans;
    }
    void pushup(int x)
    {
        int lson=x<<1,rson=lson|1;
        tree[x]=pushup(tree[lson],tree[rson],tree[x].cover,tree[x].flip);
    }
    void pushcover(int x,int k)
    {
        tree[x].cover=k;
        tree[x].flip=0;
        if(k==0)
        {
            tree[x].sum=tree[x].maxcon[1]=tree[x].lcon[1]=tree[x].rcon[1]=0;
            tree[x].maxcon[0]=tree[x].lcon[0]=tree[x].rcon[0]=tree[x].r-tree[x].l+1;
        }
        else
        {
            tree[x].sum=tree[x].maxcon[1]=tree[x].lcon[1]=tree[x].rcon[1]=tree[x].r-tree[x].l+1;
            tree[x].maxcon[0]=tree[x].lcon[0]=tree[x].rcon[0]=0;
        }
    }
    void pushflip(int x)
    {
        tree[x].flip^=1;
        tree[x].sum=tree[x].r-tree[x].l+1-tree[x].sum;
        swap(tree[x].maxcon[0],tree[x].maxcon[1]);
        swap(tree[x].lcon[0],tree[x].lcon[1]);
        swap(tree[x].rcon[0],tree[x].rcon[1]);
    }
    void pushdown(int x)
    {
        int lson=x<<1,rson=lson|1;
        if(tree[x].l==tree[x].r)return;
        if(tree[x].cover!=-1)
        {
            pushcover(lson,tree[x].cover);
            pushcover(rson,tree[x].cover);
            tree[x].cover=-1;
        }
        if(tree[x].flip!=0)
        {
            pushflip(lson);
            pushflip(rson);
            tree[x].flip=0;
        }
    }
    void build(int x,int l,int r)
    {
        tree[x]=(point){l,r,0,{0,0},{0,0},{0,0},-1,0};
        if(l==r)
        {
            if(a[l])tree[x].sum=tree[x].maxcon[1]=tree[x].lcon[1]=tree[x].rcon[1]=1;
            else tree[x].maxcon[0]=tree[x].lcon[0]=tree[x].rcon[0]=1;
            return;
        }
        int mid=(tree[x].l+tree[x].r)>>1,lson=x<<1,rson=lson|1;
        build(lson,l,mid);build(rson,mid+1,r);
        pushup(x);
    }
    void modify_cover(int x,int l,int r,int k)
    {
        pushdown(x);
        if(l<=tree[x].l&&r>=tree[x].r){pushcover(x,k);return;}
        int mid=(tree[x].l+tree[x].r)>>1,lson=x<<1,rson=lson|1;
        if(l<=mid)modify_cover(lson,l,r,k);
        if(r>mid)modify_cover(rson,l,r,k);
        pushup(x);
    }
    void modify_flip(int x,int l,int r)
    {
        pushdown(x);
        if(l<=tree[x].l&&r>=tree[x].r){pushflip(x);return;}
        int mid=(tree[x].l+tree[x].r)>>1,lson=x<<1,rson=lson|1;
        if(l<=mid)modify_flip(lson,l,r);
        if(r>mid)modify_flip(rson,l,r);
        pushup(x);
    }
    point query_sum(int x,int l,int r)
    {
        pushdown(x);
        if(l<=tree[x].l&&r>=tree[x].r)return tree[x];
        int mid=(tree[x].l+tree[x].r)>>1,lson=x<<1,rson=lson|1;
        point ans=(point){0,0,0,{0,0},{0,0},{0,0},-1,0};
        if(l<=mid)ans=pushup(query_sum(lson,l,r),ans,-1,0);
        if(r>mid)ans=pushup(ans,query_sum(rson,l,r),-1,0);
        return ans;
    }
    point query_maxcon(int x,int l,int r)
    {
        pushdown(x);
        if(l<=tree[x].l&&r>=tree[x].r)return tree[x];
        int mid=(tree[x].l+tree[x].r)>>1,lson=x<<1,rson=lson|1;
        point ans=(point){0,0,0,{0,0},{0,0},{0,0},-1,0};
        if(l<=mid)ans=pushup(query_maxcon(lson,l,r),ans,-1,0);
        if(r>mid)ans=pushup(ans,query_maxcon(rson,l,r),-1,0);
        return ans;
    }
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)a[i]=read();
        build(1,1,n);
        for(int i=1;i<=m;i++)
        {
            int opt=read(),ll=read()+1,rr=read()+1;
            switch(opt)
            {
                case 0:modify_cover(1,ll,rr,0);break;
                case 1:modify_cover(1,ll,rr,1);break;
                case 2:modify_flip(1,ll,rr);break;
                case 3:printf("%d\n",query_sum(1,ll,rr).sum);break;
                case 4:printf("%d\n",query_maxcon(1,ll,rr).maxcon[1]);break;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    从spring官网下载spring 架包
    bootstrap-dialog插件的使用
    underscore.js,js工具库
    datatables,表格
    formvalidation表单验证
    数字千分位处理,number.js,js保留两位,整数强制保留两位小数
    js精确计算
    django F和Q 关键字使用
    django 的多对多关系
    django中的一对一的关系
  • 原文地址:https://www.cnblogs.com/pjykk/p/16496934.html
Copyright © 2020-2023  润新知