在dls的数据结构中级课那学了最大字段和的线段树写法,对于这道题,我们要维护的信息有:
- 区间左边0/1的个数,
- 区间右边0/1的个数
- 区间最长0/1的长度
- 区间的赋值标记
- 区间的取反标记
- 整个区间的长度
- 对于 1 ~ 4 是很基本的最大字段和操作
- 对于 两种不同的标记,打标记是有时间顺序的,区间赋0/1,可以覆盖区间取反的标记,而区间取反的标记是在区间赋0/1的基础上进行的,标记下传也要先下传区间赋0/1的标记,再下传区间取反的标记。
struct info
{
int s0,ls0,rs0,ms0,s1,ls1,rs1,ms1;
};
info operator +(const info &a,const info &b)
{
info t;
t.s0=a.s0+b.s0;
t.s1=a.s1+b.s1;
t.ls0=a.ls0;
t.ls1=a.ls1;
t.rs0=b.rs0;
t.rs1=b.rs1;
int asz=a.s0+a.s1;
int bsz=b.s0+b.s1;
if(a.ls0==asz)
t.ls0=asz+b.ls0;
if(b.rs0==bsz)
t.rs0=bsz+a.rs0;
if(a.ls1==asz)
t.ls1=asz+b.ls1;
if(b.rs1==bsz)
t.rs1=bsz+a.rs1;
t.ms0=max({a.ms0,b.ms0,a.rs0+b.ls0});
t.ms1=max({a.ms1,b.ms1,a.rs1+b.ls1});
return t;
}
struct segtree
{
struct info val;
int sz,tag1,tag2;
}seg[N*4];
void update(int id)
{
seg[id].val=seg[id*2].val+seg[id*2+1].val;
}
void settag(int id,int tag)
{
int sz=seg[id].sz;
if(tag==0)
{
seg[id].tag2=0,seg[id].tag1=0;
seg[id].val={sz,sz,sz,sz,0,0,0,0};
}
else if(tag==1)
{
seg[id].tag2=0,seg[id].tag1=1;
seg[id].val={0,0,0,0,sz,sz,sz,sz};
}
if(tag==2)
{
seg[id].tag2^=1;
swap(seg[id].val.s0,seg[id].val.s1);
swap(seg[id].val.ls0,seg[id].val.ls1);
swap(seg[id].val.rs0,seg[id].val.rs1);
swap(seg[id].val.ms0,seg[id].val.ms1);
}
}
void pushdown(int id)
{
if(seg[id].tag1!=-1)
settag(id*2,seg[id].tag1),
settag(id*2+1,seg[id].tag1);
if(seg[id].tag2)
settag(id*2,2),
settag(id*2+1,2);
seg[id].tag1=-1,seg[id].tag2=0;
}
void build(int id,int l,int r)
{
seg[id].sz=r-l+1;
seg[id].tag1=-1,seg[id].tag2=0;
if(l==r)
{
int x; cin>>x;
if(x==0)
seg[id].val={1,1,1,1,0,0,0,0};
else seg[id].val={0,0,0,0,1,1,1,1};
return;
}
int mid=(l+r)>>1;
build(id*2,l,mid);
build(id*2+1,mid+1,r);
update(id);
}
void modify(int id,int l,int r,int ql,int qr,int tag)
{
if(l==ql&&r==qr)
{
settag(id,tag);
return;
}
pushdown(id);
int mid=(l+r)>>1;
if(qr<=mid)
modify(id*2,l,mid,ql,qr,tag);
else if(ql>mid)
modify(id*2+1,mid+1,r,ql,qr,tag);
else
modify(id*2,l,mid,ql,mid,tag),
modify(id*2+1,mid+1,r,mid+1,qr,tag);
update(id);
}
info query(int id,int l,int r,int ql,int qr)
{
if(ql==l&&qr==r)
{
return seg[id].val;
}
pushdown(id);
int mid=(l+r)>>1;
if(qr<=mid)
return query(id*2,l,mid,ql,qr);
else if(ql>mid)
return query(id*2+1,mid+1,r,ql,qr);
else return query(id*2,l,mid,ql,mid)+query(id*2+1,mid+1,r,mid+1,qr);
}
void solve()
{
int n,q; cin>>n;
cin>>q;
build(1,1,n);
for(int i=1;i<=q;i++)
{
int op,l,r; cin>>op>>l>>r;
l++,r++;
if(op<=2)
{
modify(1,1,n,l,r,op);
}
else
{
if(op==3)
cout<<query(1,1,n,l,r).s1<<endl;
else
cout<<query(1,1,n,l,r).ms1<<endl;
}
}
return;
}
本文来自博客园,作者:magicat,转载请注明原文链接:https://www.cnblogs.com/magicat/p/17282382.html
分类:
数据结构
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通