题目描述:
曾经发明了自动刷题机的发明家 SHTSC 又公开了他的新发明:脑洞治疗仪——一种可以治疗他因为发明而日益增大的脑洞的神秘装置。
为了简单起见,我们将大脑视作一个 01 序列。11代表这个位置的脑组织正常工作,00代表这是一块脑洞。1 0 1 0 0 0 1 1 1 0
1 1 1 1 0 0 1 0 0 0
如果再用第11号位置到第44号位置去修补第88号位置到第1010号位置:
0 0 0 0 0 0 1 1 1 1
这是因为脑洞治疗仪会把多余出来的脑组织直接扔掉。
如果再用第77号位置到第1010号位置去填补第11号位置到第66号位置:1 1 1 1 0 0 0 0 0 0
输入输出格式
输入格式:
第一行两个整数 n、m,表示 SHTSC 的大脑可分为从1到n编号的n个连续区域,有m个操作。
以下m行每行是下列三种格式之一:0 l r:SHTSC 挖了一个范围为[l,r]的脑洞。1 $l_0$ $r_0$ $l_1$ $r_1$:SHTSC 进行了一次脑洞治疗,用从$l_0$ 到$r_0$ 的脑组织修补$l_1$到$r_1$ 的脑洞。2 $l$ $r$:SHTSC 询问$[l,r]$区间内最大的脑洞有多大。上述区间均在$[1,n]$范围内。输出格式:
对于每个询问,输出一行一个整数,表示询问区间内最大连续脑洞区域有多大。
思路
很多题解都提到了GSS系列的最大连续子段和问题,那我就不说了,我只说这道题中我用到的一些奇妙的解法
1.反着定义这道题要求的是最大连续0的长度,那么用最大子段和的话如果你按1走统计的就不是0,而是1,我们可以将1定义为-inf,0定义为1,再跑最大子段和即可2.分开存gss中要存一个区间和sum,但由于上面的定义形式,这玩意儿显然不能表示0(或1)的数量,我们可以用一个mix,专门存0或1的数量大体思路:
0.首先,给1节点打上-inf的lazy标记,表示没有脑洞
1.对于0操作,区间覆盖,打lazy标记后直接修改即可2.对于2操作,GSS标准查询即可3.对于1操作,先求出l1,r1的脑组织数,再全挖成脑洞,之后填进l2,r2去即可(函数写成int式,优先填左区间,填完后返回剩余脑洞数)代码:
#include#include #include #include #define rii register int i#define rij register int j#define rs 262144#define int long longusing namespace std;struct tree{ long long lmax,rmax,sum,lazy,maxn,mix;}x[1000005];int n,m,p;void pushdown(int nl,int nr,long long val,int bh){ int mid=(nl+nr)/2; long long cd=mid-nl+1; x[bh*2].lazy=val; x[bh*2].lmax=val*cd; x[bh*2].rmax=val*cd; x[bh*2].sum=val*cd; x[bh*2].maxn=val*cd; x[bh*2].mix=(val%2)*cd; x[bh*2+1].mix=(val%2)*cd; x[bh*2+1].lazy=val; x[bh*2+1].lmax=val*cd; x[bh*2+1].rmax=val*cd; x[bh*2+1].sum=val*cd; x[bh*2+1].maxn=val*cd; x[bh].lazy=0;}void fg(int l,int r,int nl,int nr,int bh){ if(l nr) { r=nr; } if(x[bh].lazy==1) { return; } if(x[bh].lazy==-100000) { pushdown(nl,nr,x[bh].lazy,bh); } if(l==nl&&r==nr) { x[bh].lazy=1; x[bh].sum=(r-l+1); x[bh].lmax=(r-l+1); x[bh].rmax=(r-l+1); x[bh].maxn=(r-l+1); x[bh].mix=(r-l+1); return; } int mid=(nl+nr)/2; if(l<=mid) { fg(l,r,nl,mid,bh*2); } if(r>=mid+1) { fg(l,r,mid+1,nr,bh*2+1); } x[bh].mix=x[bh*2].mix+x[bh*2+1].mix; x[bh].sum=x[bh*2].sum+x[bh*2+1].sum; x[bh].lmax=max(x[bh*2].lmax,x[bh*2].sum+x[bh*2+1].lmax); x[bh].rmax=max(x[bh*2+1].rmax,x[bh*2+1].sum+x[bh*2].rmax); x[bh].maxn=max(x[bh*2].maxn,max(x[bh*2+1].maxn,x[bh*2].rmax+x[bh*2+1].lmax));}int sum(int l,int r,int nl,int nr,int bh){ if(l nr) { r=nr; } if(l==nl&&r==nr) { return x[bh].mix; } if(x[bh].lazy!=0&&nl!=nr) { pushdown(nl,nr,x[bh].lazy,bh); } int mid=(nl+nr)/2; int ans=0; if(l<=mid) { ans+=sum(l,r,nl,mid,bh*2); } if(r>=mid+1) { ans+=sum(l,r,mid+1,nr,bh*2+1); } return ans;}int add(int l,int r,int nl,int nr,int sl,int bh){ if(l nr) { r=nr; } if(x[bh].lazy!=0) { pushdown(nl,nr,x[bh].lazy,bh); } if(l==nl&&r==nr&&sl>=(r-l+1)) { sl-=x[bh].mix; x[bh].mix=0; x[bh].lmax=(-100000)*(r-l+1); x[bh].rmax=(-100000)*(r-l+1); x[bh].maxn=(-100000)*(r-l+1); x[bh].sum=(-100000)*(r-l+1); x[bh].lazy=-100000; return sl; } int mid=(nl+nr)/2; if(l<=mid&&sl!=0) { sl=add(l,r,nl,mid,sl,bh*2); } if(r>=mid+1&&sl!=0) { sl=add(l,r,mid+1,nr,sl,bh*2+1); } x[bh].mix=x[bh*2].mix+x[bh*2+1].mix; x[bh].sum=x[bh*2].sum+x[bh*2+1].sum; x[bh].lmax=max(x[bh*2].lmax,x[bh*2].sum+x[bh*2+1].lmax); x[bh].rmax=max(x[bh*2+1].rmax,x[bh*2+1].sum+x[bh*2].rmax); x[bh].maxn=max(x[bh*2].maxn,max(x[bh*2+1].maxn,x[bh*2].rmax+x[bh*2+1].lmax)); return sl;}tree query(int l,int r,int nl,int nr,int bh){ tree an,bn; if(l nr) { r=nr; } if(x[bh].lazy!=0) { pushdown(nl,nr,x[bh].lazy,bh); } if(nl==l&&nr==r) { an=x[bh]; return an; } int ltt=(nl+nr)/2; if(l<=ltt&&r<=ltt) { return an=query(l,r,nl,ltt,bh*2); } if(r>ltt&&l>ltt) { return bn=query(l,r,ltt+1,nr,bh*2+1); } else { an=query(l,r,nl,ltt,bh*2); bn=query(l,r,ltt+1,nr,bh*2+1); an.maxn=max(an.maxn,max(bn.maxn,an.rmax+bn.lmax)); an.lmax=max(an.lmax,an.sum+bn.lmax); an.rmax=max(bn.rmax,bn.sum+an.rmax); an.sum=an.sum+bn.sum; return an; }}signed main(){// freopen("1.in","r",stdin);// freopen("1.out","w",stdout); scanf("%lld%lld",&n,&m); x[1].lazy=-100000; for(rii=1;i<=m;i++) { int l,r; scanf("%lld",&p); if(p==0) { scanf("%lld%lld",&l,&r); fg(l,r,1,rs,1); } if(p==2) { scanf("%lld%lld",&l,&r); tree ans=query(l,r,1,rs,1); if(ans.maxn<0) { ans.maxn=0; } printf("%lld\n",ans.maxn); } if(p==1) { int l1,l2,r1,r2; scanf("%lld%lld%lld%lld",&l2,&r2,&l1,&r1); int ltt=sum(l2,r2,1,rs,1); ltt=(r2-l2+1)-ltt; fg(l2,r2,1,rs,1); if(ltt>(r2-l2+1)) { ltt=r2-l2+1; } add(l1,r1,1,rs,ltt,1); } }}