Educational Codeforces Round 113 (Rated for Div. 2)D

Posted 吃花椒的妙酱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 113 (Rated for Div. 2)D相关的知识,希望对你有一定的参考价值。

题目大意:平面坐标上若干横竖线,线上有若干点,两个点之间的距离只能通过已知的横竖线表示,求多少对点对它们的距离大于曼哈顿距离

思路:横竖算贡献

我们发现两条直线形成交点,这个交点的贡献为0,如上图的点9,它与其他任何点的曼哈顿距离都能表示。

剩下的点,要么在已知的竖线,要么在已知竖线上,分两种情况讨论

我们先看在已知竖线上的点,上图中有3,4,5,2

其中3,4,5分为一小组,2单独分为一组,它们中间被一条横线分开了,3,4,5到2它们的曼哈顿距离也是能被表示出的,只有同个小组中才有可能出现无法表示出的点对。

什么情况不能被表示出呢,3,4,5它们两两都无法表示出

 我现在在3下面加个点10,发现3和10的曼哈顿距离是可以表示出的,也就是在一条竖线上的点对也是可以表示出的

我们利用容斥,ans = 总点对数 - 在同一直线上的点对数

横线同理,不多赘述

注意,对竖线情况,讨论划分小组的时候,用upperbound找第一条大于等于当前点的纵坐标,如3,4,5去找1所在的那条横线,2去找6798所在的横线,依此分组

算同一直线的点对,因为是逐个点插入的,不清楚同一直线上多少点,所以是加一个点,然后算前面已经在同一直线上的点的数量的方法做

像3,4,5,10插入到点10的时候,发现3在同一直线,把(3,10)算进去

一开始用Map记录次数然后tle了,改成桶就过了

#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
using namespace std;
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define pb push_back
#define IOS ios::sync_with_stdio(false)
#define int long long
#define all(v) v.begin(),v.end()
#define inf 0x3f3f3f3f
#define pii pair<int,int>
#define fi first
#define se second
typedef long long ll;
const int N=2e5+10;
const int M=3e5+10;
int n,k,m;
int a[N],b[N];
pii p[M];
int xx[N],yy[N];//次数
void solve()
{
    vector<int > v[n+10],h[m+10];
    int ans=0;
    _for(i,1,k)
    {
        int x = p[i].fi;
        int y = p[i].se;
        //划分小组用upper,因为直线唯一性,另一个点upper和lowwer一样的
        int px = upper_bound(a+1,a+1+n,x) - a-1;
        int py = upper_bound(b+1,b+1+m,y) - b-1;
        if( a[px]==x && b[py]==y ) continue;
        if( b[py]==y )//在y=b上
        {
            v[px].pb(py);
        }
        else
        {
            h[py].pb(px);
        }
    }
    _for(i,0,n-1)
    {
        int siz = v[i].size();
        ans += siz*(siz-1)/2;
        for(auto u:v[i])
        {
            ans -= yy[u];
            yy[u]++;
        }
        for(auto u:v[i])
        {
            yy[u]--;
        }
    }
    _for(i,0,m-1)
    {
        int siz = h[i].size();
        ans += siz*(siz-1)/2;
        for(auto u:h[i])
        {
            ans -= xx[u];
            xx[u]++;
        }
        for(auto u:h[i])
        {
            xx[u]--;
        }
    }
    cout<<ans<<endl;
}
signed main()
{
    ///!!!
//    freopen("data.txt","r",stdin);
    //!!!=
    IOS;
    int T;cin>>T;
    while( T-- )
    {
        cin>>n>>m>>k;
        _for(i,1,n) cin>>a[i];
        _for(i,1,m) cin>>b[i];
        _for(i,1,k) cin>>p[i].fi>>p[i].se;
        solve();
    }
}

以上是关于Educational Codeforces Round 113 (Rated for Div. 2)D的主要内容,如果未能解决你的问题,请参考以下文章

Educational Codeforces Round 7 A

Educational Codeforces Round 7

Educational Codeforces Round 90

Educational Codeforces Round 33

Codeforces Educational Codeforces Round 54 题解

Educational Codeforces Round 27