目录
Description
有 \(n\) 条纵向街道, \(m\) 条横向街道,\(k\) 个人在这些街道上,求有几对人相遇所走的路程大于其曼哈顿距离
State
\(2<=n,m<=2*10^5\)
\(2<=k<=3*10^5\)
\(0<=x,y<=10^6\)
\(1<=t<=1000\)
Input
2
2 2 4
0 1000000
0 1000000
1 0
1000000 1
999999 1000000
0 999999
5 4 9
0 1 2 6 1000000
0 4 8 1000000
4 4
2 5
2 2
6 3
1000000 1
3 8
5 8
8 8
6 8
Output
2
5
Solution
很明显要使用贡献法,如果有两个在不同 \(x\) 轴上的点很容易想到向附近的 \(y\) 轴作垂线,这样,又可以发现,只有当这两个点分别位于一个最小的矩形上时,才会对答案做贡献
比如题目中的 \(3,4\) 两点,他们所位于的 \(x=2\) 和 \(x=6\) 同时处在一个不可以分割的矩形中,所以他们之间的距离是大的。
当有一个点\((x, y)\) 在 \(x\) 轴上,而且其上限为 \(maxy(maxy!=y)\),下限为 \(miny(miny!=y)\),那么这个点所得到的贡献为 \([miny, maxy]\) 这段区间内点的个数 \(-\) 同时位于 \(x\) 轴上的点的个数
Code
const int N = 1e6 + 5;
ll n, m, _;
int i, j, k;
vector<int> row, col;
int havex[N], havey[N];
map<pii, int> mpx, mpy;
void clear()
{
row.clear();
col.clear();
fill(havex, 0);
fill(havey, 0);
mpx.clear();
mpy.clear();
}
signed main()
{
//IOS;
rush(){
sddd(n, m, k);
rep(i, 1, n){
row.pb(read());
}
rep(i, 1, m){
col.pb(read());
}
ll ans = 0;
while(k --> 0){
int x, y;
sdd(x, y);
auto nx = lower_bound(row.begin(), row.end(), x);
auto ny = lower_bound(col.begin(), col.end(), y);
if(x == *nx && y == *ny) continue;
if(x == *nx){
ans += havey[*ny] - mpy[{*ny, *nx}];
havey[*ny] ++;
mpy[{*ny, *nx}] ++;
}
else{
ans += havex[*nx] - mpx[{*nx, *ny}];
havex[*nx] ++;
mpx[{*nx, *ny}] ++;
}
}
pll(ans);
clear();
}
//PAUSE;
return 0;
}