一种不用map的做法
查看原帖
一种不用map的做法
1502443
ljx1018楼主2024/11/6 21:55

注:本篇解法相交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;
}

2024/11/6 21:55
加载中...