目录

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;
}