问题描述:
海里有很多灯塔。海的范围是[1, 10^7] × [1, 10^7]
。
每个灯塔都可以照亮西南和东北地区。光的力量应该覆盖任何距离。
如果灯塔A和B在那里照明区域,说它们可以相互照亮。
输入有n + 1行: 第一行是灯塔的数量。 第n行 行的第二行是灯塔的水平和垂直坐标。
输出有一行: 这对灯箱可以相互照亮。
例如:
intput:
3
2 2
4 3
5 1
输出:
1
请注意:
灯塔的坐标为int。所有灯塔的水平和垂直坐标都不同。
1 ≤ x, y ≤ 10^7
我的代码效率非常低。请帮我修改我的代码。非常感谢你!
这是我的代码。
#include<stdlib.h>
int main()
{
int n,i,j,s;
int *x,*y;
scanf("%d",&n);
x=(int *)malloc(n*sizeof(int));
y=(int *)malloc(n*sizeof(int));
for(i=0;i<n;i++)
{
scanf("%d %d",&x[i],&y[i]);
}
s=0;
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
{
if((x[i]>x[j]&&y[i]>y[j])||(x[i]<x[j]&&y[i]<y[j]))
s++;
}
printf("%d\n",s);
free(x);
free(y);
return 0;
}
答案 0 :(得分:1)
我没有足够的声誉直接发表评论,所以我会详细说明并在此留下答案。
你的算法使用嵌套循环进行成对计算并且具有O(n 2 )时间复杂度,这就是为什么你的算法对于大输入来说很慢的原因(这里大的并不意味着坐标值,但是灯塔的数量)。首先让我们看看我们可以做些什么来优化,输入样本:
3
1 1(P a )
2 2(P b )
3 3(P c 子>)
使用您的算法,执行逻辑将是:
实际上有多余的计算可以消除:
确定现有的灯塔是否可以照亮新增加的灯塔。
请注意,P a 的NE区域实际上包含P b 的NE区域,因此如果新的灯塔属于P b 的NE区域,隐含地意味着它被P a 以及P b 所照亮。因此,如果我们在海中有P a 和P b 并添加P c ,我们实际上不需要用P <计算两次sub> a 和P b 分开。
假设我们有以下记录记录灯塔的照明交叉区域:
一个。计数= 0; R = {}
湾添加P a ,R = {[( - ∞,-∞),(1,1)] - > [P a ],[(1,1) ,(∞,∞)] - &gt; [P a ]}([(-∞,-∞),(1,1)]和[(1,1),(∞,∞) )]定义两个带有对角点的矩形区域)
c。添加P b ,P b 在[(1,1),(∞,∞)]中(这意味着[P a ]可以照亮P b ),找到可以被P b 照亮的[P a ]中的所有灯塔,即P a < / sub>,count + = 1,R = {[( - ∞,-∞),(1,1)] - &gt; [P a ,P b ] ,[( - ∞,1),(1,2)] - &GT; [P <子> b'/子>],[(1,-∞),(2,1)] - &GT; [P <子> b'/子>],[(1,1),(2,2)] - &GT; [P <子>一子>,P <子> b'/子>],[(1- ,2),(2,∞)] - &GT; [P <子> b'/子>],[(2,1),(∞,2)] - &GT; [P <子> b'/子>],[(2,2),(∞,∞)] - &GT; [P <子>一子>,P <子> b'/子>]}
d。添加P c ,P c 在[(2,2),(∞,∞)]中,找到[P a ,P b ]可以被[P a ,P b ]照亮,即P a , P b ,count + = 2,更新R(太长了所以我在这里省略它)
您可能想要表示的一个数据结构R是一个分段树1。这里适用的分段树是二维的。我建议您查看现有的帖子How to code 2D segment tree?,然后尝试实现自己的帖子。