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