D. Inconvenient Pairs(二分&容斥)

因为每个点 ( x , y ) (x,y) (x,y)要么 x x x在直线上要么 y y y在直线上。

显然 x x x在直线上的点与 y y y在直线上的点不会产生贡献,因为两个距离相等。

所以 x x x在直线上的点只会对其同类产生贡献, y y y同理。

因为两者等价,不妨只考虑 x x x在直线上的点。

D. Inconvenient Pairs(二分&容斥)_ios

如果此时两个点的上面的直线 y y y相同,显然会产生贡献。因为这两个点都夹在相同的两直线之间。

否则这两个点肯定可以通过某条直线到达。

D. Inconvenient Pairs(二分&容斥)_算法_02

然后还需注意的是,对于 x x x相同的点也是没有贡献的,因为两点在同一直线上。

查找直线用二分即可。

所以每次增加的贡献就是: c n t y − p y c n t ( y , x ) cnt_{y}-pycnt_{{(y,x)}} cntypycnt(y,x)

每次计算完, c n t y + 1 , p y c n t ( y , x ) + 1 cnt_y+1,pycnt_{(y,x)}+1 cnty+1,pycnt(y,x)+1

y y y类直线同理。

// Problem: D. Inconvenient Pairs
// Contest: Codeforces - Educational Codeforces Round 113 (Rated for Div. 2)
// URL: https://codeforces.ml/contest/1569/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// Date: 2021-09-09 10:04:44
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=2e5+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define IOS ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\n",a[n]); 
}
//if have char input #define should cancel
#define getchar()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
template <typename T>
inline T& read(T& r) {
    r = 0; bool w = 0; char ch = getchar();
    while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
    while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
    return r = w ? -r : r;
}
int t,n,m,k;
int mx[N],my[N];
map<PII,int>mxy,myx;
int x[N],y[N];
int main(){
	read(t);while(t--){
		mxy.clear(),myx.clear();
		read(n),read(m),read(k);
		rep(i,1,n) read(x[i]),mx[i]=0;
		rep(i,1,m) read(y[i]),my[i]=0;
		ll ans=0;
		while(k--){
			int u,v;read(u),read(v);
			int cx=lower_bound(x+1,x+n+1,u)-x;
			int cy=lower_bound(y+1,y+m+1,v)-y;
			if(u==x[cx]){
				if(v==y[cy]) continue;
				ans+=my[cy]++ - myx[{cy,cx}]++;
			}
			else ans+=mx[cx]++ - mxy[{cx,cy}]++;
		}
		printf("%lld\n",ans);
	}
	return 0;
}