[CF-Edu113]D. Inconvenient Pairs

目录

[CF-Edu113]D. Inconvenient Pairs

题目

有\(n\)条垂直于\(x\)轴的直线(竖直直线),\(m\)条平行于\(x\)轴的直线(水平直线),和\(k\)个在直线上的点,你可以沿着直线从一个点走到另一个点,求有多少对点的曼哈顿距离严格大于沿直线走的距离(称作"不方便点对").

[CF-Edu113]D. Inconvenient Pairs

思路

什么情况下不合法,必要条件是什么?

那题面的图来举例:

[CF-Edu113]D. Inconvenient Pairs

图中3,4,5两两互为不方便点对,特点就是共同夹在两条相邻的"水平直线之间".

那是不是只要两个点夹在两条相邻的水平/竖直直线之间就是不方便点对呢?

按这个思路1,6,7也应该两两互为不方便点对,但显然"6,7"不是,明显的特征就是它们同在一条水平直线上,所以,减去这种情况就好了.

在举了一些特殊情况的例子(比如1,3; 3,4),发现都没有漏或者重复计算,所以我们就可以愉快地切掉这题啦!

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
template <class T>
T read() {
	T re = 0;
	char c = getchar();
	bool negt = false;
	while(c < '0' || c > '9')
		negt |= (c == '-') , c = getchar();
	while(c >= '0' && c <= '9')
		re = (re << 1) + (re << 3) + c - '0' ,c = getchar();
	return negt ? -re : re;
}
const int N = 300010;

struct Node {
	int x , y;
}p[N];
bool CmpByX(Node a , Node b) {
	return a.x < b.x;
}
bool CmpByY(Node a , Node b) {
	return a.y < b.y;
}

int n , m , k;
int x[N] , y[N];

int vis[1000003];

void solve() {
	n = read<int>() , m = read<int>() , k = read<int>();
	for(int i = 1 ; i <= n ; i++)
		x[i] = read<int>();
	for(int i = 1 ; i <= m ; i++)
		y[i] = read<int>();
	for(int i = 1 ; i <= k ; i++)
		p[i].x = read<int>() , p[i].y = read<int>();
	
	long long ans = 0;
	int i = 1 , j = 1;
	sort(p + 1 , p + k + 1 , CmpByX);
	for(int q = 1 ; q < n ; q++) {
		while(p[i].x <= x[q] && i < k) ++i;
		while(p[j].x < x[q + 1] && j <= k) ++j;
		--j;
		ans += 1ll * (j - i + 1) * (j - i) / 2;
		
		for(int l = i ; l <= j ; l++)
			ans -= vis[p[l].y] , ++vis[p[l].y];
		for(int l = i ; l <= j ; l++)
			vis[p[l].y] = 0;
	}
	
	sort(p + 1 , p + k + 1 , CmpByY);
	i = j = 1;
	for(int q = 1 ; q < m ; q++) {
		while(p[i].y <= y[q] && i < k) ++i;
		while(p[j].y < y[q + 1] && j <= k) ++j;
		--j;
		ans += 1ll * (j - i + 1) * (j - i) / 2; 
		
		for(int l = i ; l <= j ; l++)
			ans -= vis[p[l].x] , ++vis[p[l].x];
		for(int l = i ; l <= j ; l++)
			vis[p[l].x] = 0;
	}
	printf("%lld\n" , ans);
}
int main() {
	int T = read<int>();
	while(T--) {
		solve();
	}
	return 0;
}
上一篇:LeetCode 2006. Count Number of Pairs With Absolute Difference K【数组/哈希表】


下一篇:QT——信号与槽