TsingHua OJ 上不能使用<algorithm>头文件,因此需要手写快排(刚开始写的时候自己就出了很多问题....),另外本题需要在给横坐标排序后,需要记录纵坐标的顺序对的数量,因此,最快的算法貌似只有归并排序或者树状数组的方法进行顺序对的查找和记录了,时间度为O(nlogn),另外此前需要一次对横坐标的排序,这里用快排。

灯塔(LightHouse)


描述

海上有许多灯塔,为过路船只照明。

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

若灯塔A、B均在对方的照亮范围内,则称它们能够照亮彼此。比如在图二的实例中,蓝、红灯塔可照亮彼此,蓝、绿灯塔则不是,红、绿灯塔也不是。

现在,对于任何一组给定的灯塔,请计算出其中有多少对灯塔能够照亮彼此。

输入

共n+1行。

第1行为1个整数n,表示灯塔的总数。

第2到n+1行每行包含2个整数x, y,分别表示各灯塔的横、纵坐标。

输出

1个整数,表示可照亮彼此的灯塔对的数量。

Example

Input

3
2 2
4 3
5 1

Output

1

限制

对于90%的测例:1 ≤ n ≤ 3×105

对于95%的测例:1 ≤ n ≤ 106

全部测例:1 ≤ n ≤ 4×106

灯塔的坐标x, y是整数,且不同灯塔的x, y坐标均互异

1 ≤ x, y ≤ 10^8

时间:2 sec

内存:256 MB

提示

注意机器中整型变量的范围,C/C++中的int类型通常被编译成32位整数,其范围为[-231, 231 - 1],不一定足够容纳本题的输出。


解题思路:

  乱序的坐标对我们解题是没有帮助的,因此我们首先应该想到对横坐标(纵坐标)做一次排序,然后考虑纵坐标(横坐标)。

在这里我先对横坐标进行排序,然后从小到大对纵坐标的要求进行归纳,我们可以发现:如果存在两个灯塔A(x1,y1),B(x2,y2),那么x1<x2时,当且仅当y1<y2时,A B两灯塔才能相互beacon(照亮),因此,这道题可以转化为当横坐标顺序确定时,去记录纵坐标的顺序对数量。

  例如A(1,2),B(2,4),C(3,5),那么显然ABC中任两灯塔间可以相互beacon,其对数就是三对。

  ——我们用顺序对来描述就是:A B C顺序摆放,其中AB,AC,BC的纵坐标(<2,4>,<2,5>,<4,5>)各为一个顺序对,因此有三对灯塔可以相互beacon,这与我们的分析是一致的。

时间度分析:

  那么在分析完这道题目后,我们就需要做两件事情,第一件事就是对横坐标进行一次排序,第二件事就是利用某种算法计算出横坐标排序后,纵坐标的顺序对的数量。

  在题目中给出 全部测例:1 ≤ n ≤ 4×10这个数据量是很大的,因此我们必须要用快排对横坐标排序,时间度认为是O(nlogn),第二件事中,联系到逆序对的记录,我们可以用到的最快算法有归并排序和树状数组,这里我们试用归并排序进行顺序对记录,时间度也认为是O(nlogn)。

  以下是实现Code:

 #include<stdio.h>

 #define MAX 4000005
long ans; struct Light{
int x, y;
}l[MAX]; int tmp[MAX]; /*快排*/
void quickSort(int low, int high)
{
int i = low;
int j = high;
Light x = l[low]; //设置一个基准点
do{
while (l[i].x < x.x) i++; //Let l[i].x >= x
while (l[j].x > x.x) j--; //Let l[j].x <= x
if(i <= j){ //SWAP
Light t = l[i];
l[i] = l[j];
l[j] = t;
i++; j--;
}
} while (i <= j); //使得p两侧满足 左<=p,右>=p
if(i < high) quickSort(i, high);
if(j > low ) quickSort(low, j);
} void merge(int low, int mid, int high)
{
int s = low, t = mid + , k = low;
while (s <= mid && t <= high){
if (l[s].y < l[t].y){
ans += high - t + ; //顺序对-右侧未放入的date数量
tmp[k++] = l[s++].y;
}
else tmp[k++] = l[t++].y;
}
if (s == mid + ) while (k <= high) tmp[k++] = l[t++].y;
else while (k <= high) tmp[k++] = l[s++].y;
//COPY
for (int i = low; i <= high; i++) l[i].y = tmp[i];
} /*归并排序*/
void mergeSort(int low, int high)
{
if (low < high){
int mid = (low + high) / ;
mergeSort(low, mid);
mergeSort(mid + , high);
merge(low, mid, high);
}
} int main()
{
int n;
scanf("%d", &n);
for (int i = ; i < n; i++)
scanf("%d%d", &l[i].x, &l[i].y);
quickSort(, n - );//横坐标快排
mergeSort(, n - );//纵坐标归并排序并记录顺序对 printf("%ld\n", ans); return ;
}

小墨- -原创

  尽管如此,但是我们依然只能A掉95%的样例,说明我们的算法依然不够快,依然要进行优化,那么在这里效果最显著的方法

  一个就是改归并排序树状数组可能相对要更快一些,另一个就是优化手写的快速排序算法,可以采用生成随机数或者采用三数取中等等优化方法使得我们手写的快排更趋近稳定,但是由于时间原因,小编没有尝试下去。

ACM/ICPC 之 快排+归并排序-记录顺序对(TSH OJ-LightHouse(灯塔))的更多相关文章

  1. 2017 ACM/ICPC Asia Regional Shenyang Online 记录

    这场比赛全程心态爆炸…… 开场脑子秀逗签到题WA了一发.之后0贡献. 前期状态全无 H题想复杂了,写了好久样例过不去. 然后这题还是队友过的…… 后期心态炸裂,A题后缀数组理解不深,无法特判k = 1 ...

  2. 2017 ACM/ICPC Asia Regional Guangxi Online 记录

    题目链接  Guangxi 感觉这场比赛完全是读题场啊…… 比赛过程中丢失了一波进度,最后想开题的时候已经来不及了…… Problem A 按题意模拟……按照那个矩阵算就可以了 #include &l ...

  3. 2017 ACM/ICPC Asia Regional Beijing Online 记录

    题目链接  Beijing

  4. 2017 ACM/ICPC Asia Regional Xian Online 记录

    题目链接  Xian

  5. 2017 ACM/ICPC Asia Regional Qingdao Online 记录

    题目链接  Qingdao Problem C AC自动机还不会,暂时暴力水过. #include <bits/stdc++.h> using namespace std; #define ...

  6. 2017 ACM/ICPC Asia Regional Urumuqi Online 记录

    比赛题目链接  Urumuqi

  7. ACM/ICPC 之 双向链表_构造列表-模拟祖玛 (TSH OJ-Zuma(祖玛))

    这一题是TsingHua OJ上的一道题目,学堂在线的一位数据结构老师的题目(原创),所以我直接把题目先贴下来了,这道题对复习双向链表很有帮助,而且也对数据结构中List,也就是对列表的回顾也是很有帮 ...

  8. ACM/ICPC 之 优先级队列+设置IO缓存区(TSH OJ-Schedule(任务调度))

    一个裸的优先级队列(最大堆)题,但也有其他普通队列的做法.这道题我做了两天,结果发现是输入输出太过频繁,一直只能A掉55%的数据,其他都是TLE,如果将输入输出的数据放入缓存区,然后满区输出,可以将I ...

  9. Java排序算法分析与实现:快排、冒泡排序、选择排序、插入排序、归并排序(二)

    一.概述: 上篇博客介绍了常见简单算法:冒泡排序.选择排序和插入排序.本文介绍高级排序算法:快速排序和归并排序.在开始介绍算法之前,首先介绍高级算法所需要的基础知识:划分.递归,并顺带介绍二分查找算法 ...

随机推荐

  1. MD5 (摘要加密)

    MD5 约定 同样的密码,同样的加密算法,每次加密的结果是不一样 密码方案 方案一:直接 MD5 pwd = pwd.md5String; 非常不安全 方案二 MD5 + 盐 pwd = [pwd s ...

  2. C语言strdup函数

    static RD_INLINE RD_UNUSED char *rd_strdup(const char *s) { #ifndef _MSC_VER char *n = strdup(s); #e ...

  3. [转]Ubuntu 16.04建议安装

    Ubuntu 16.04发布了,带来了很多新特性,同样也依然带着很多不习惯的东西,所以装完系统后还要进行一系列的优化. 1.删除libreoffice libreoffice虽然是开源的,但是Java ...

  4. jQuery回调、递延对象总结(下篇) —— 解密jQuery.when方法

    前言: 前一篇文章中重点总结了一下then方法,它主要用来处理多个异步任务按顺序执行,即前一个任务处理完了,再继续下一个,以此类推: 而这一章节jQuery.when方法也是处理多个异步任务,它把多个 ...

  5. 自执行的匿名函数!function()

    最近有空可以让我静下心来看看各种代码,function与感叹号的频繁出现,让我回想起2个月前我回杭州最后参加团队会议的时候,@西子剑影抛出的一样的问题:如果在function之前加上感叹号 (!) 会 ...

  6. R-处理数据对象的实用函数

  7. RDS记录

    rdsafbnr32uzayn.mysql.rds.aliyuncs.com r7fysfqs90r74cm6

  8. C++中的内联成员函数与非内联成员函数

    在C++中内联成员函数与非内联成员函数的可以分为两种情况: 1.如果成员函数的声明和定义是在一起的,那么无论有没有写inline这个成员函数都是内联的,如下: using namespace std; ...

  9. C语言各种标准的

    [K&R C] 1978 年,Dennis Ritchie 和 Brian Kernighan 合作推出了<The C Programming Language>的第一版(按照惯例 ...

  10. FineUI第十三天---`列布局

    这是经典的列布局:                  <x:Panel runat=                     <Items>                      ...