纪念碑

题目大意

在N*M的网格中,有P个矩形建筑,求一个最大边长的正方形,使得网格中能找到一个放置正方形的地方,不会与建筑重合。
N,M<=10^6,P<=40000。

扫描线

如果有两条在x轴上的扫描线l与r,表示l~r-1之间可以放边长为r-l的正方形。
期望在l与r间放一个边长为r-l+1的矩形。
那么假如我们能在两条扫描线间找到最大空隙ms。
如果r-l+1<=ms,那么可以放,接下来r+1。
如果r-l+1>ms,便不能放,因此l+1。由于l~r-1之间可以放边长为r-l的正方形,l+1~r-1之间便可以放边长为r-l-1的正方形。所以r不用变。

错误的线段树

现在问题就是如何求空隙。
显然可以使用线段树,维护最大连续0。每个位置的数代表被几个障碍包含。
当r+1时,加入左边界在x=r上的矩形。
当l+1时,删除右边界在x=l-1上的矩形。
如何维护最大连续0?
我们可以维护num,lnum,rnum分别表示最大连续0,左起最大连续0,右起最大连续0。
显然

tree[p].num=max(tree[p*2].rnum+tree[p*2+1].lnum,max(tree[p*2].num,tree[p*2+1].num));
        tree[p].lnum=tree[p*2].lnum;
        if (tree[p*2].lnum==mid-l+1) tree[p].lnum+=tree[p*2+1].lnum;
        tree[p].rnum=tree[p*2+1].rnum;
        if (tree[p*2+1].rnum==r-mid) tree[p].rnum+=tree[p*2].rnum;

注意到这道题要支持区间添加与区间删减,且删减区间与添加区间一一对应,再加上一个区间只要有add标记那么最大连续0一定为0,所以我们可以不下传标记,打一个“错误”的线段树。

你可能感兴趣的:(纪念碑)