【luogu CF1569D】Inconvenient Pairs(思维)

Inconvenient Pairs

题目链接:luogu CF1569D

题目大意

有一个方形网格,然后只有一些竖着的直线和横着的直线是可以走的(会给出它们的 x 坐标或 y 坐标)。
然后会给你一些点,保证点在可以走的位置上。
然后问你有多少个点对之间的最短距离大于它们的哈密顿距离。

思路

你考虑怎样的点是会出现那样的情况的。

首先如果一个点在交叉路口,那有它的点对就不可能。

然后你会发现满足的点对一遍都是一个维度在路口上但是不在同一个路口,另一个维度就不再路口上,而且如果你拿另一个维度的路口去把这个维度分成几段,那它们是在同一段上。

然后你就随便用点东西统计一下即可。

然后记得要从两个维度来分别统计。

代码

#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long using namespace std; struct node { int x, y; int xx, yy; int xp, yp; }a[300005]; int t, n, m, k; int xx[300005], yy[300005]; int pl[300005], nm[300005]; int lstnm[300005]; ll ans; bool cmp1(node x, node y) { return x.x < y.x; } bool cmp2(node x, node y) { return x.y < y.y; } int main() { scanf("%d", &t); while (t--) { scanf("%d %d %d", &n, &m, &k); for (int i = 1; i <= n; i++) scanf("%d", &xx[i]); for (int i = 1; i <= m; i++) scanf("%d", &yy[i]); for (int i = 1; i <= k; i++) { scanf("%d %d", &a[i].x, &a[i].y); if (xx[lower_bound(xx + 1, xx + n + 1, a[i].x) - xx] == a[i].x) a[i].xx = 1, a[i].xp = 3e5 + 1; else a[i].xx = 0, a[i].xp = lower_bound(xx + 1, xx + n + 1, a[i].x) - xx; if (yy[lower_bound(yy + 1, yy + m + 1, a[i].y) - yy] == a[i].y) a[i].yy = 1, a[i].yp = 3e5 + 1; else a[i].yy = 0, a[i].yp = lower_bound(yy + 1, yy + m + 1, a[i].y) - yy; // printf("%d %d %d %d\n", a[i].xx, a[i].xp, a[i].yy, a[i].yp); } sort(a + 1, a + k + 1, cmp1); for (int i = 1; i <= k; i++) { int ii = i; pl[0] = 0; nm[a[i].yp] += !a[i].yy; if (nm[a[i].yp] == 1) pl[++pl[0]] = a[i].yp; while (i < k && a[i + 1].x == a[i].x) {i++, nm[a[i].yp] += !a[i].yy; if (nm[a[i].yp] == 1) pl[++pl[0]] = a[i].yp;} for (int j = 1; j <= pl[0]; j++) { ans += 1ll * lstnm[pl[j]] * nm[pl[j]]; lstnm[pl[j]] += nm[pl[j]]; } for (int j = ii; j <= i; j++) nm[a[j].yp] = 0; } for (int i = 1; i <= k; i++) lstnm[a[i].yp] = 0; sort(a + 1, a + k + 1, cmp2); for (int i = 1; i <= k; i++) { int ii = i; pl[0] = 0; nm[a[i].xp] += !a[i].xx; if (nm[a[i].xp] == 1) pl[++pl[0]] = a[i].xp; while (i < k && a[i + 1].y == a[i].y) {i++, nm[a[i].xp] += !a[i].xx; if (nm[a[i].xp] == 1) pl[++pl[0]] = a[i].xp;} for (int j = 1; j <= pl[0]; j++) { ans += 1ll * lstnm[pl[j]] * nm[pl[j]]; lstnm[pl[j]] += nm[pl[j]]; } for (int j = ii; j <= i; j++) nm[a[j].xp] = 0; } for (int i = 1; i <= k; i++) lstnm[a[i].xp] = 0; printf("%lld\n", ans); ans = 0; } return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/luogu_CF1569D.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(48)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示