题解:AT_abc366_e [ABC366E] Manhattan Multifocal Ellipse
写在前面的话
本篇题解篇幅较长,但是如果你想彻底把这道题弄懂,请静下心来,把这篇题解看完,相信对你的提升会很大。如果有看不懂的地方欢迎给我发私信,我会详细地解答。
题目简述
平面上有
后面半句话也就是,
思路
对上式进行变形:
我们可以枚举所有的
实现
枚举
思考
这里先说结论,从点
更为形式化的,设之前的答案为
为什么这么做可以?
看图,其中黄色点是
从图中我们可以直观的看到从点
和我们的结论是一样的。
第一个问题已经解决了,我们还需要
预处理所有的
这里这道题也就讲完了。
最后总结一下算法流程:
-
预处理所有
y 的可能值,放进桶里,前缀和。 -
用类似的办法,枚举
x 的可能值,对每个x 算出有多少个y 满足条件。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 6e6 + 10;
int x[maxn], y[maxn];
int cnt[maxn], sum[maxn];
int mpx[maxn], mpy[maxn];
signed main()
{
int n, d;
cin >> n >> d;
for (int i = 1; i <= n; i++)
{
cin >> x[i] >> y[i];
mpx[x[i] + 2000000]++, mpy[y[i] + 2000000]++;
}
int now = 0, l = 0, r = n, ans = 0;
for (int i = 1; i <= n; i++)
{
now += abs((-(2e6 + 1)) - y[i]);
}
for (int i = -2e6; i <= 2e6; i++)
{
now += l, now -= r;
if (now <= d)
cnt[now]++;
l += mpy[i + 2000000], r -= mpy[i + 2000000];
}
for (int i = 0; i <= d; i++)
{
sum[i] = sum[i - 1] + cnt[i];
}
now = 0, l = 0, r = n;
for (int i = 1; i <= n; i++)
{
now += abs(-(2e6 + 1) - x[i]);
}
for (int i = -2e6; i <= 2e6; i++)
{
now += l, now -= r;
if (now <= d)
ans += sum[d - now];
l += mpx[i + 2000000], r -= mpx[i + 2000000];
}
cout << ans;
return 0;
}