ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

高度模式化的线段树写法

2022-07-20 10:35:09  阅读:128  来源: 互联网

标签:return int 线段 tree 模式化 xmid lson ans 写法


(水)

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;
}

标签:return,int,线段,tree,模式化,xmid,lson,ans,写法
来源: https://www.cnblogs.com/pjykk/p/16496934.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有