题意
给你一个大矩形,其中有很多小矩形在里面(有重叠),让你在里面找一个最大的正方形的边长(里面不包含任何小矩形)
数据范围
对于30%的数据,p<=1000.
对于70%的数据,p<=30000.
对于100%的数据,p<=400000,m,n<=1000000.
分析
一看就是各种猥琐的线段树维护,另外我在比赛时yy出另一种线段树做法,但是感觉太猥琐就没有打。。、
正解
扫描线。
维护两条扫描线l,r,表示当前矩形所在的范围。那么我们再在线段树里面维护最长连续在y轴没有被其他矩形覆盖的长度,设其为ms。
那么若是r-l+1>ms,说明不能放,我们便调整l,l=l+1;
那么若是r-l+1<=ms,说明l~r之间可以放,我们便继续看看答案是否能加大,r=r+1;
错误的线段树
当然我们在调整l,r的过程中我们还是要把右边界在l的矩形的标记去掉,
把左边界在r的矩形的矩形的标记加上。
那么我们的标记应该如何处理呢?
我们发现这题的修改的区间是一一对应的,而我们便没有必要把整棵线段树都更新一遍它的懒标记,我们只需要把这个区间的标记改变即可,顺便把它的维护的值全部赋值为0,这样就相当它没有更新了。
具体的:
更新连续最大长度。
t[p,1]表示整个区间里不从两边开始中间的最大长度
t[p,2]为从左边开始的最大长度。
t[p,3]为从右边开始的最大长度。
t[p,4]为标记
procedure make(p,l,r:longint);
var mid:longint;
begin
if t[p,4]>0 then begin t[p,1]:=0;t[p,2]:=0;t[p,3]:=0;exit;end;//标记若为1,那么便把它的所有东西赋为0.
if l=r then begin t[p,1]:=1;t[p,2]:=1;t[p,3]:=1;exit;end;
mid:=(l+r)shr 1;
t[p,1]:=max(t[p*2,3]+t[p*2+1,2],max(t[p*2,1],t[p*2+1,1]));
t[p,2]:=t[p*2,2];
if (t[p*2,2]=mid-l+1) then inc(t[p,2],t[p*2+1,2]);
t[p,3]:=t[p*2+1,3];
if (t[p*2+1,3]=r-mid) then inc(t[p,3],t[p*2,3]);
end;