高度模式化的线段树写法
作者:互联网
(水)
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