题目大意:
一个长为
,宽为
的矩形.它由
个
的正方形组成。
左下角的正方形的坐标为
,
右上角的正方形的坐标为
。
有
片土地被用来修建建筑,,每一个建筑可以看做是一个左下角为
,右上角为
的矩形。
问能在这个
矩形中的空地(没有建筑覆盖的)上找到的一个最大的正方形的边长是多少。
分析:
将
升序排列,那么一个矩形就可以通过在
位置时对
,在
位置时对其
,来表示这个矩形的贡献,那么就是扫描线的思想了。
设
个指针
,
表示
轴上
都是存在一个或者多个
使得这段内存在长为
的空地,
这时候我们用线段树维护
中所有加进来的边,
此时我们只进行
的操作,暂不考虑
,
这样我们就可以知道一个
在
时,是否满足
都是空地,然后我们考虑这时候
该如何修改指针,如果当前的满足条件的
的最大连续长度为
,则
时,我们右移指针
,直到
,
此时是不变的,
改变,
随之改变
然后此时右移的过程中,将
带来的影响消掉(即进行它身上所有的
操作)
然后
就是这个过程中的
{
}
然后对于求一段连续的最长的合法
,
分为合法和不合法,
可以转换成
串中求最长连续
的个数,
建一颗线段树,树中每个节点都记录,从左端点往右最多有多少个连续
,从右端点往左最多有多少个连续
,当前区间最长的连续
的长度为多少
然后转移就是
转移给
,挺显然的,自己手画一下就好
然后就可以做到
了
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <cstring>
#include <algorithm>
#define lson(x) x * 2
#define rson(x) x * 2 + 1
#define N 1000005
#define M 400005
using namespace std;
typedef long long ll;
struct Code { int maxlen, llen, rlen, lazy; }C[N*4];
struct Node { int x, y1, y2, z; }a[M*2];
int Answer, cnt, n, m, p;
bool cmp(Node aa, Node bb)
{
if (aa.z == bb.z) return aa.x < bb.x;
return aa.z > bb.z;
}
void Addcder(int x, int y1, int y2, int z)
{
a[++cnt].x = x, a[cnt].y1 = y1, a[cnt].y2 = y2, a[cnt].z = z;
}
void update(int x, int l, int r)
{
int mid = (l + r) >> 1;
C[x].llen = C[lson(x)].llen;
C[x].rlen = C[rson(x)].rlen;
if (C[lson(x)].llen == mid - l + 1) C[x].llen += C[rson(x)].llen;
if (C[rson(x)].rlen == r - mid) C[x].rlen += C[lson(x)].rlen;
C[x].maxlen = max(max(C[lson(x)].maxlen, C[rson(x)].maxlen), C[lson(x)].rlen + C[rson(x)].llen);
}
void Build(int x, int l, int r)
{
C[x].maxlen = C[x].llen = C[x].rlen = r - l + 1;
if(l == r) return;
int mid = (l + r) >> 1;
Build(lson(x), l, mid);
Build(rson(x), mid + 1, r);
}
void change(int x, int l, int r, int L, int R, int num)
{
if (L <= l && r <= R)
{
C[x].lazy += num;
if (!C[x].lazy)
{
if (l == r) C[x].maxlen = C[x].llen = C[x].rlen = 1;
else update(x, l, r);
}
else C[x].maxlen = C[x].llen = C[x].rlen = 0;
return;
}
int mid = (l + r) >> 1;
if (L <= mid) change(lson(x), l, mid, L, R, num);
if (R > mid) change(rson(x), mid + 1,r, L, R, num);
if(!C[x].lazy)
{
if (l == r) C[x].maxlen = C[x].llen = C[x].rlen = 1;
else update(x, l, r);
}
else C[x].maxlen = C[x].llen = C[x].rlen = 0;
}
int main()
{
scanf("%d %d %d", &n, &m, &p);
for (int i = 1; i <= p; i++)
{
int x1, y1, x2, y2;
scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
Addcder(x1, y1, y2, 1);
Addcder(x2, y1, y2, - 1);
}
sort(a + 1, a + cnt + 1, cmp);
Build(1, 1, m);
int now = 1, cop = p + 1, l = 1, r = 1;
for (; r <= n; r++)
{
while (a[now].x == r && now <= p) change(1, 1, m, a[now].y1, a[now].y2, 1), now++;
Answer = max(Answer, min(C[1].maxlen, r - l + 1));
while (C[1].maxlen < r - l + 1)
{
while (a[cop].x == l && cop <= p * 2) change(1, 1, m, a[cop].y1, a[cop].y2, - 1), cop++;
l++;
}
}
printf("%d\n", Answer);
return 0;
}