在 push_up 函数中,无论如何当前区间的最大连续空房个数都需要更新,因此要将其先赋 0 再比较。
push_up
tp.len = tpx2.len + tpx2add.len;
tp.l0 = (tpx2.l0 == tpx2.len) ? tpx2.l0 + tpx2add.l0 : tpx2.l0;
tp.r0 = (tpx2add.r0 == tpx2add.len) ? tpx2add.r0 + tpx2.r0 : tpx2add.r0;
tp.v = 0; // <--- 注意这里
vs_max(p, tpx2add.v, tpx2add.maxl);
vs_max(p, tpx2.r0 + tpx2add.l0, tpx2.pr - tpx2.r0 + 1);
vs_max(p, tpx2.v, tpx2.maxl);
在 add_tag 函数中,区间退房时要将该区间记录的最大连续空房的左端点设为当前区间左端点。
add_tag
tp.l0 = tp.len;
tp.r0 = tp.len;
tp.v = tp.len;
tp.maxl = tp.pl; // <--- 注意这里
tp.tag = 0;
注意 query 函数的实现。
正确实现:
int query(int p, int m)
{
if (tp.v < m)
return 0;
else if (tp.pl == tp.pr)
return tp.pl;
push_down(p);
if (tpx2.v >= m)
return query(px2, m);
else if (tpx2.r0 + tpx2add.l0 >= m)
return tpx2.pr - tpx2.r0 + 1;
else
return query(px2add, m);
}
错误示范:
int query(int p, int m)
{
if (tp.v < m)
return 0;
else if (tp.v == m)
return tp.maxl;
else
{
push_down(p);
int left = query(px2, m), right = query(px2add, m), mid = tpx2.r0 + tpx2add.l0;
if (left == 0)
{
if (mid >= m)
return tpx2.pr - tpx2.r0 + 1;
else
return right;
}
else
return left;
}
}
#define px2 (p << 1)
#define px2add (p << 1 | 1)
#define tp t[p]
#define tpx2 t[px2]
#define tpx2add t[px2add]
struct kkk
{
int v, l0 = 0, r0 = 0, len = 0, pl, pr, tag = -1, maxl = 0;
} t[4 * LEN];
// v 表示当前区间最大连续 1 的长度
// l0、r0 表示左边/右边连续的 0(即空房)的个数
// pl、pr 表示区间左、右端点
// tag 为标记,0 表示区间退房,1 表示区间住房
// maxl 为当前区间最大连续 1 那一段的左端点