描述

海上有许多灯塔,为过路船只照明。从平面上看,海域范围是[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)问题的更多相关文章

  1. 【Tsinghua OJ】祖玛(Zuma)问题

    描述 祖玛是一款曾经风靡全球的游戏,其玩法是:在一条轨道上初始排列着若干个彩色珠子,其中任意三个相邻的珠子不会完全同色.此后,你可以发射珠子到轨 道上并加入原有序列中.一旦有三个或更多同色的珠子变成相 ...

  2. 【Tsinghua OJ】范围查询(Range)问题

    [问题描述]数轴上有n个点,对于任一闭区间 [a, b],试计算落在其内的点数. [输入]第一行包括两个整数:点的总数n,查询的次数m.第二行包含n个数,为各个点的坐标.以下m行,各包含两个整数:查询 ...

  3. 灯塔(LightHouse)

    Description As shown in the following figure, If another lighthouse is in gray area, they can beacon ...

  4. 【Tsinghua OJ】多米诺骨牌(domino)问题

    (domino.c/cpp)[问题描述] 小牛牛对多米诺骨牌有很大兴趣,然而她的骨牌比较特别,只有黑色和白色的两种.她觉 得如果存在连续三个骨牌是同一种颜色,那么这个骨牌排列便是不美观的.现在她有n个 ...

  5. 【Tsinghua OJ】循环移位(Cycle)

    Description Cycle shifting refers to following operation on the sting. Moving first letter to the en ...

  6. 【Tsinghua OJ】隧道(Tunel)问题

    描述 现有一条单向单车道隧道,每一辆车从隧道的一端驶入,另一端驶出,不允许超车 该隧道对车辆的高度有一定限制,在任意时刻,管理员希望知道此时隧道中最高车辆的高度是多少 现在请你维护这条隧道的车辆进出记 ...

  7. Tsinghua OJ Zuma

    Description Let's play the game Zuma! There are a sequence of beads on a track at the right beginnin ...

  8. ACM/ICPC 之 快排+归并排序-记录顺序对(TSH OJ-LightHouse(灯塔))

    TsingHua OJ 上不能使用<algorithm>头文件,因此需要手写快排(刚开始写的时候自己就出了很多问题....),另外本题需要在给横坐标排序后,需要记录纵坐标的顺序对的数量,因 ...

  9. 清华学堂 LightHouse

    灯塔(LightHouse) Description As shown in the following figure, If another lighthouse is in gray area, ...

随机推荐

  1. Qt之QSystemTrayIcon

    简述 QSystemTrayIcon类为应用程序在系统托盘中提供一个图标. 现代操作系统通常在桌面上提供一个特殊的区域,称为系统托盘或通知区域,长时间运行的应用程序可以显示图标和短消息. 简述 内容 ...

  2. Linux基础:软件安装(rpm,yum,源代码)

    Software Installation on Linux Linux安装分为rpm包(可通过yum或者是rpm命令安装)和源码包(源代码或者是编译过的二进制码)两种. Linux是开源系统,很多应 ...

  3. struts2在web.xml中的配置

    <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2 ...

  4. python中字符与ascii码转换

    ASCII码转字符用chr()函数:  字符转ASCII码用ord()函数:  

  5. 使用自定义模板为Myeclipse添加新建Filter的功能

    第一步:单击windowpreference菜单项,在打开的窗口中,依次展开Java.Editor.Templates列表项,然后在打开的Templates面板中,单击[New]按钮 使用这个模板非 ...

  6. 【转载】如何在德州仪器网站查找和下载PCB封装

    德州仪器的网站做得相当不错,查找IC资料和下载IC封装样样给力.那么如何在TI网站上能够快速查找到自已需要的PCB封装呢?下面我来告诉你. 1.       在浏览器中输入网址http://weben ...

  7. 使用js给页面显示的图片添加水印效果

    功能描述:使用Jquery 给页面的图片添加 版权信息水印. 这里的水印并不是真的把每一张图片上都添加了水印.而是在图片的上方添加了一个层,层中包含了水印图片效果就像是图片上加了水印. 功能原理:1, ...

  8. The APR based Apache Tomcat Native library 异常解决办法

    tomat在linux服务器上启动报The APR based Apache Tomcat Native library which allows optimal performance in pro ...

  9. 第三章 XHTML 表单

    1.表单的主要作用在于在网页上提供一个图形用户界面,以采集和提交用户输入的数据. 2.HTML表单元素和属性可以分为两种类型:定义表单整体结构,使浏览器知道如何处理表单数据的元素:创建输入控件的元素. ...

  10. 【bzoj2281】[Sdoi2011]黑白棋

    博弈论---Nimk问题. dp再搞搞. 很容易看出,该游戏的终态是每两个棋子都紧靠着.当一颗棋子移动,另一方与该棋子对应的那一刻可以立即追上,使得仍旧紧靠,最终棋子动弹不得,游戏结束. 还能看出,对 ...