【Tsinghua OJ】灯塔(LightHouse)问题
描述
海上有许多灯塔,为过路船只照明。从平面上看,海域范围是[1, 10^8] × [1, 10^8] 。

(图一)
如图一所示,每个灯塔都配有一盏探照灯,照亮其东北、西南两个对顶的直角区域。探照灯的功率之大,足以覆盖任何距离。灯塔本身是如此之小,可以假定它们不会彼此遮挡。

(图二)
若灯塔A、B均在对方的照亮范围内,则称它们能够照亮彼此。比如在图二的实例中,蓝、红灯塔可照亮彼此,蓝、绿灯塔则不是,红、绿灯塔也不是。
现在,对于任何一组给定的灯塔,请计算出其中有多少对灯塔能够照亮彼此。
输入
共n+1行。
第1行为1个整数n,表示灯塔的总数。
第2到n+1行每行包含2个整数x, y,分别表示各灯塔的横、纵坐标。
输出
1个整数,表示可照亮彼此的灯塔对的数量。
输入样例
3
2 2
4 3
5 1
输出样例
1
限制
对于90%的测例:1 ≤ n ≤ 3×105
对于95%的测例:1 ≤ n ≤ 106
全部测例:1 ≤ n ≤ 4×106
灯塔的坐标x, y是整数,且不同灯塔的x, y坐标均互异
1 ≤ x, y ≤ 10^8
提醒
注意机器中整型变量的范围,C/C++中的int类型通常被编译成32位整数,其范围为[-231, 231 - 1],不一定足够容纳本题的输出。
时间:2s,内存:256MB
【solution】
很容易的,我们能将这道题和逆序对联系起来。
原因在于A和B能够相互照亮的条件(假设A(x)<B(x))就是B在A的右上方。注意原题注明了:不同灯塔的x, y坐标均互异。
所以只要我们首先将所有点按照x坐标排序,接下来在y坐标中统计所有“非逆序对”或者说“顺序对”,再求和,就可以了。
而问题的关键就在于在这样的数据规模下如何快速的统计出“顺序对”的个数。
如果只是单纯的O(n^2)的算法显然是效率不够的。
那,如何从向量中快速的统计出“顺序对”的个数?
这里大概思考之后可以联想到 归并排序。
归并排序的关键也就是用分治的策略,将原问题一分为二的递归下去,最后的关键步骤只是将左右两个有序的区间合并起来即可。
而很快会发现,在合并的过程中似乎我们就可以顺便统计“顺序对”的个数。
考虑这样的一种情形:
目前左右两个有序区间,分别有指针 i, j 指向该区间下一个要合并的元素。
当a[i] < a[j]的时候(不可能相等,原题目已经说明),此时 a[i] 就要被合并。
而 a[j] 以及所有右区间大于 a[j] 的元素 其实都与 a[i] 构成“顺序对”。
统计完后,i 指向 i++ 的元素,且区间也都是没有重叠部分的,所以也并不会重复计数。
这样在归并排序合并的同时,也将所有的“顺序对”无重复无遗漏地记录了下来。
算法复杂度也就是O(nlogn)的。
源码如下:
#include <stdio.h> #define L 1000005 int y[L], le[L], ri[L];
long ans = ; void qsort(int a[], int b[], int l, int r)
{
int i, j, x, t;
i = l; j = r; x = a[i + ((j - i)>>)];
do
{
while (x > a[i]) i++;
while (x < a[j]) j--;
if (i <= j)
{
t = a[i]; a[i] = a[j]; a[j] = t;
t = b[i]; b[i] = b[j]; b[j] = t;
i++; j--;
}
} while (i <= j);
if (i < r) qsort(a, b, i, r);
if (j > l) qsort(a, b, l, j);
} void Merge(int l, int mi, int r)
{
int i, j, k, n1 = mi - l + , n2 = r - mi;
const int MAX = ; for (i = ; i <= n1; i++) le[i] = y[l + i - ];
for (i = ; i <= n2; i++) ri[i] = y[mi + i]; le[n1 + ] = MAX; ri[n2 + ] = MAX; i = ; j = ;
for (k = l; k <= r; k++)
{
if (le[i] > ri[j]) y[k] = ri[j++];
else
{
y[k] = le[i++];
ans += long(n2) - j + ;
}
} } void Merge_Sort(int l, int r)
{
int mi;
if (l == r) return;
mi = l + ((r - l)>>);
Merge_Sort(l, mi);
Merge_Sort(mi + , r);
Merge(l, mi, r);
} int main(void)
{
int n, x[L];
scanf("%d", &n);
for (int i = ; i <= n; i++)
{
scanf("%d %d\n", &x[i], &y[i]);
} qsort(x, y, , n); Merge_Sort(, n); printf("%ld\n", ans); return ;
}
要注意题目中的提示部分,用 int 类型可能不足以容纳结果数字。对 x 的排序使用的是快排(快速排序)。
此程序可以通过 Tsinghua OJ 上 95%的数据,也就是 n > 1 * 10^6 的那个点无法通过(即使改了代码中的 L 也不行,Runtime error (exitcode: 11)),暂无解。
【Tsinghua OJ】灯塔(LightHouse)问题的更多相关文章
- 【Tsinghua OJ】祖玛(Zuma)问题
描述 祖玛是一款曾经风靡全球的游戏,其玩法是:在一条轨道上初始排列着若干个彩色珠子,其中任意三个相邻的珠子不会完全同色.此后,你可以发射珠子到轨 道上并加入原有序列中.一旦有三个或更多同色的珠子变成相 ...
- 【Tsinghua OJ】范围查询(Range)问题
[问题描述]数轴上有n个点,对于任一闭区间 [a, b],试计算落在其内的点数. [输入]第一行包括两个整数:点的总数n,查询的次数m.第二行包含n个数,为各个点的坐标.以下m行,各包含两个整数:查询 ...
- 灯塔(LightHouse)
Description As shown in the following figure, If another lighthouse is in gray area, they can beacon ...
- 【Tsinghua OJ】多米诺骨牌(domino)问题
(domino.c/cpp)[问题描述] 小牛牛对多米诺骨牌有很大兴趣,然而她的骨牌比较特别,只有黑色和白色的两种.她觉 得如果存在连续三个骨牌是同一种颜色,那么这个骨牌排列便是不美观的.现在她有n个 ...
- 【Tsinghua OJ】循环移位(Cycle)
Description Cycle shifting refers to following operation on the sting. Moving first letter to the en ...
- 【Tsinghua OJ】隧道(Tunel)问题
描述 现有一条单向单车道隧道,每一辆车从隧道的一端驶入,另一端驶出,不允许超车 该隧道对车辆的高度有一定限制,在任意时刻,管理员希望知道此时隧道中最高车辆的高度是多少 现在请你维护这条隧道的车辆进出记 ...
- Tsinghua OJ Zuma
Description Let's play the game Zuma! There are a sequence of beads on a track at the right beginnin ...
- ACM/ICPC 之 快排+归并排序-记录顺序对(TSH OJ-LightHouse(灯塔))
TsingHua OJ 上不能使用<algorithm>头文件,因此需要手写快排(刚开始写的时候自己就出了很多问题....),另外本题需要在给横坐标排序后,需要记录纵坐标的顺序对的数量,因 ...
- 清华学堂 LightHouse
灯塔(LightHouse) Description As shown in the following figure, If another lighthouse is in gray area, ...
随机推荐
- Thread 总结
进程:是一个正在执行的程序 每一个进程执行都有一个执行顺序.该顺序是一个执行路劲,后者叫一个控制单元. 线程:就是进程中的一个独立控制单元. 线程在控制着进程的执行 一个进程中至少有个一个线程 Jav ...
- target标签对于优化用户体验的作用
最近开始关注target="_blank"标签,是源于对咨询区的采纳工作.帖子内容页是在原页面加载,这样问题就来了,每采纳完一个问题,必须得后退好几次才可以,很不方便.后来按ctr ...
- CentOS 下的MySQL配置
先贴出代码(/etc/my.cnf)如下: #The following options will be passed to all MySQL clients [client] #password ...
- 解决tomcat部署多个虚拟机时报IllegalStateException: Web app root system property already set to 的问题
解决tomcat部署多个虚拟机时报IllegalStateException: Web app root system property already set to 的问题 在web.xml中添加如 ...
- linux bash: sqlplus: command not found 错误处理
在oracle用户下 ,执行sqlplus命令,抛出如上错误. 解决办法: 1.su oracle 2.cd /home/oracle 3. 执行命令 source .bash_pro ...
- iOS只执行一次的方法
IOS开发(64)之GCD任务最多只执行一次 1 前言 使用 dispatch_once 函数 在 APP 的生命周期内来保证你想确保每段代码只执行一次,即使它在代码的不同地方多次调用(比如单例的初始 ...
- Black 全面分析
Black 全面分析 如果有Block语法不懂的,可以参考fuckingblocksyntax,里面对于Block 为了方便对比,下面的代码我假设是写在ViewController子类中的 1.第一部 ...
- 转: html表单中get方式和post方式的区别
1.Get是用来从服务器上获得数据,而Post是用来向服务器上传递数据. 2.Get将表单中数据的按照variable=value的形式,添加到action所指向的URL后面,并且两者使用“?”连接 ...
- pthreads 0.1.0 测试报告
1 可以说已经稳定了 2 发现一个算是技巧的东西吧:在线程之间传递的类的实例,要保证能正常工作,需要类本身extends Stackable,所有方法都弄成public--我原来了写了一个数据库操作类 ...
- 一模 (5) day2
第一题: 题目大意:使得 x^x 达到或超过 n 位数字的最小正整数 x 是多少? n<=2*10^9 解题过程: 1.以前看到过这题了,一个数x的位数=(int)lg(x)+1 换一下底就是 ...