【题解】AT2394 [ARC071B] 井井井 / ###
\rm{Description}
在平面直角坐标系中,给定
\rm{Solution}
\rm{subtask} \rm{1}
考虑暴力做法,枚举矩形的左上角和右下角,也就是求:
时间复杂度是
\rm{subtask} \rm{2}
对于任意一个矩形,想要确定它,只需要固定一条平行于
所以最终的答案可以写成:
记
这样可以得到
\rm{subtask} \rm{3}
思路:
对于满分做法,我们期望
考虑如何快速求出所有平行于
对于平行于
如果到此为止您看懂了,那可以直接看代码了,如果没看懂,请看下面这部分。
具体地:
定义一个线段是基本线段,当且仅当线段的两个端点之间不存在另一个端点,那么我们可以将每条线段拆成基本线段的和的形式,之后分别计算每条基本线段的贡献。
比如:
对于这张图,线段长度和为
那么我们将上图中每个线段表示成基本线段的和的形式,比如
现在考虑如何计算每条基本线段的贡献。
根据小学数学知识,线段
对于平行于
\rm{Code}
#include <bits/stdc++.h>
#define int long long
#define MAXN 100008
using namespace std;
int n, m, x[MAXN], y[MAXN];
int A, B; //A为所有平行于 x 轴的线段长度和,B为平行于 y 轴的线段长度和
const int mod = 1e9 + 7;
signed main() {
scanf("%lld%lld", &n, &m);
for(int i = 1; i <= n; i++) scanf("%lld", &x[i]);
for(int i = 1; i <= m; i++) scanf("%lld", &y[i]);
sort(x + 1, x + n + 1); //横纵坐标升序排序
sort(y + 1, y + m + 1);
for(int i = 2; i <= n; i++) { //计算与x轴平行的所有线段的长度和
A = (A + (x[i] - x[i - 1]) * (i - 1) * (n - i + 1)) % mod;
}
for(int i = 2; i <= m; i++) {
B = (B + (y[i] - y[i - 1]) * (i - 1) * (m - i + 1)) % mod;
}
printf("%lld\n", A * B % mod);
return 0;
}