注:本篇解法相交map十分复杂,仅为对代码优化的讨论
前置知识:离散化,sort,没有map!
本题所有大佬们都用map秒了,但是我不会用,能写吗?
那就学map
答案是可以靠优化避免TLE或WLE或RE
(当然map还是要学的)
首先如果开一个二维数组会RE,因为n^2太大了,所以考虑离散化,用b[n]存储点的坐标。在要判断周围是否有房屋时通过遍历b实现。
但是,问题又来了。每次查找都会花费k的时间,又有k次查找,就导致时间为O(k^2),会超时,所以还要优化
我们用结构体存坐标,把b排序,这样就只要判断b[i]后是否有相邻的就可以了。可以证明,只要找到b[i]的右边和下边节点,统计个数,就可以得到最终答案,并且只要找到2个就可以结束循环
如下:
for(int j=i;j<=i+n;j++)
{
if(b[j].x==x+1&&b[j].y==y||b[j].x==x&&b[j].y==y+1)
{
num++;
sum++;
}
if(sum==2)break;
}
但是,还是会超时,还能优化吗?
仔细思考就会发现,由于已经对b排序了,所以只要搜最多n次就能找到答案,因为最坏情况是一行中的每一个都有房子,所以必须找到b[n+1]才能找到b[i]的下边
此外,因为b[i]的右边一定在b[i]的下一个,所以特判一下
如下:
for(int i=0;i<k;i++)
{
x=b[i].x;
y=b[i].y;
if(b[i+1].x==x&&b[i+1].y==y+1)num++;
for(int j=i+1;j<=i+n;j++)
{
if(b[j].x==x+1&&b[j].y==y)
{
num++;
break;
}
}
}
但是,还是TLE,就没办法了吗?
实际上,就差最后一步了!
容易想到,由于排序过,当正在搜的点的行数已经超过x+1时,就可以肯定这个点下面不会再有了,可以直接break
终于,AC到手!
最后附上AC代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e7+10;
long long n,k,num;
struct zb{
int x,y;
}b[N];
bool cmp(zb x,zb y)
{
if(x.x!=y.x)
return x.x<y.x;
return x.y<y.y;
}
int main() {
cin>>n>>k;
int x,y;
for(int i=0;i<k;i++)
{
cin>>x>>y;
b[i].x=x;
b[i].y=y;
}
// cout<<endl;
sort(b,b+k,cmp);
// for(int i=0;i<k;i++)
// cout<<b[i].x<<" "<<b[i].y<<endl;
for(int i=0;i<k;i++)
{
x=b[i].x;
y=b[i].y;
if(b[i+1].x==x&&b[i+1].y==y+1)num++;
for(int j=i+1;j<=i+n;j++)
{
if(b[j].x==x+1&&b[j].y==y)
{
num++;
break;
}
if(b[j].x>x+1)break;
}
}
cout<<num;
return 0;
}
完