题解 CF1401E 【Divide Square】
只有两种情况,会产生一个新的块:
-
square 的对边被一条 segment 连接,如图:
-
两条 segment 相交,如图:
注意,因为每条 segment 必然有一段与 square 的一边相连,则两条相交必会产生一个新的块。
所以,我们可以分这两种情况来计算所有的块。
首先,
第一种情况是很好处理的,对于读入的某条横边或者竖边,如果它的两个端点分别为
对于第二种情况,我们可以抽象为一个单点修改,区间查询的问题。
比如,我们把横边看作「修改」,竖边看作「查询」。
下面,我们依次处理横坐标位于
尝试动态维护一个数组
- 定义操作
\operatorname{\large{M}\small{ODIFY}}\normalsize{(t, p, v)} 表示在t 时刻,将\text{cover}_p 增加v ; - 定义操作
\operatorname{\large{Q}\small{UERY}}\normalsize{(t, l, r)} 表示询问在t 时刻,查询\sum\limits_{i=l}^{r}\text{cover}_i 。
描述一下一条横边
描述一下一条竖边
那么,将所有操作按照 「时间不同时,按照时间升序;时间相同时,先修改后查询」 的方式排序,这就成为了一个标准的单点修改,区间查询的问题,可以用树状数组/线段树解决。
时间复杂度
#include <bits/stdc++.h>
#define int long long
#define AddModification(t, p, v) mdfy[++m0] = (modification){t, p, v};
#define AddQuery(t, l, r) qry[++q0] = (query){t, l, r};
using namespace std;
const int N = 1e5 + 5, S = 1e6 + 5;
int y[N], lx[N], rx[N], x[N], ly[N], ry[N];
int ans = 1, n, m, o[S], m0, q0;
struct modification
{
int t, p, v;
bool operator < (const modification &oth) const { return t < oth.t; }
} mdfy[N << 1];
struct query
{
int t, l, r;
bool operator < (const query &oth) const { return t < oth.t; }
} qry[N << 1];
void Modify(modification &opt)
{
for(int p = opt.p; p < S; p += p & -p)
o[p] += opt.v;
}
int Query(query &opt)
{
int res = 0;
for(int p = opt.r; p; p -= p & -p)
res += o[p];
for(int p = opt.l - 1; p; p -= p & -p)
res -= o[p];
return res;
}
signed main()
{
scanf("%lld %lld", &n, &m);
for(int i = 1; i <= n; i++)
{
scanf("%lld %lld %lld", &y[i], &lx[i], &rx[i]);
if(lx[i] == 0 && rx[i] == 1000000) ans++;
y[i]++; lx[i]++; rx[i]++;
AddModification(lx[i] - 1, y[i], 1);
AddModification(rx[i], y[i], -1);
}
for(int i = 1; i <= m; i++)
{
scanf("%lld %lld %lld", &x[i], &ly[i], &ry[i]);
if(ly[i] == 0 && ry[i] == 1000000) ans++;
x[i]++; ly[i]++; ry[i]++;
AddQuery(x[i], ly[i], ry[i]);
}
sort(mdfy + 1, mdfy + m0 + 1);
sort(qry + 1, qry + q0 + 1);
int nowm = 1, nowq = 1;
for(; nowm <= m0 && mdfy[nowm].t == 0; nowm++) Modify(mdfy[nowm]);
for(int t = 1; t < S; t++)
{
for(; nowq <= q0 && qry[nowq].t == t; nowq++) ans += Query(qry[nowq]);
for(; nowm <= m0 && mdfy[nowm].t == t; nowm++) Modify(mdfy[nowm]);
}
printf("%lld\n", ans);
return 0;
}