这道题是前几天训练赛的题目,我自己写的时候没有考虑到数据为1e9范围开了数组炸了,结束后队友告诉我可以采用map的方法,之前没有咋了解map用法,借此机会顺便也学习了一下。
如果你没学过map等STL,可以来这看–>STL方法
直达链接F-ice T
题目
Example
Input
11
5 10
7 6
7 4
7 2
1 8
3 8
1 6
3 6
2 4
2 6
5 8
Output
3
思想
这道题首先给你一个定义告诉你什么是”T“数—满足一条线上有三个等距离的点且中间点与自己所在的垂直线上有点,连起来就是一个”T“数。
题目给你n组数据,每组都是横纵坐标。(要点就是范围是int,直接排除了int的做法)
这道题最简单直接暴力的办法就是直接搜索,分为两块,行扫描和列扫描。
这就是样例作出的图,可以发现T的朝向可以是四个的方向的,这也是行扫描和列扫描的原因。
既然数组解决不了问题,我们考虑将行指向的坐标和列指向的坐标分别存在两个map类型变量内,搜行的时候找到了符合条件的中间点就从以中间点那一列内检索是否出现过点(当然要排除自己)。
因此,我们考虑采用map内嵌套一个set(找数据的时候快一点,跑find就可以了)。
TIP:为啥采用map呢?主要是map内自动帮你排好first的数据,找起来比较有条理,要真的想放unorder_map也是没问题的,还会快一点
(就像这个图一样存数据)
AC代码
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define pre(i,a,b) for(int i=a;i>=b;--i)
#define m(x) memset(x,0,sizeof x)
typedef long long ll;
const int maxn = 1e6+10;
#define PI acos(-1)
//第一个map存储从横坐标指向的纵坐标下标,第二个map存储从纵坐标指向的横坐标下标
map<int, set<int> >x;
map<int, set<int> >y;
int main()
{
//读入数据
int n, a, b, ans = 0;
scanf("%d", &n);
while (n--)
{
scanf("%d%d", &a, &b);
x[a].insert(b);y[b].insert(a);
}
//建立迭代器
map<int, set<int> >::iterator it;
set<int>::iterator it1, it2;
//从上到下遍历行
for (it = x.begin(); it != x.end(); ++it)
{
//it->first指向的就是横行坐标
int idx = it->first;
//遍历set数组
for (it1 = x[idx].begin(); it1 != x[idx].end(); ++it1)
//这里it2 = ++it1,--it1其实就是it2=it1+1的意思,但是指针不能自增么,所以曲线救国了
for (it2 = ++it1,--it1; it2 != x[idx].end(); ++it2)
{
int tmp = *it1 + *it2;
//这里前半部分判断it1与it2之间留有足够的空格且是奇数个,后半部分从map_y中找是否有存在idx横坐标
//以此来满足题目的横线三点等条件
if (!(tmp & 1) && y[tmp >> 1].count(idx))
//这里直接将条件成立的那一列数目减去重复自己的个数加入ans
ans += y[tmp >> 1].size() - 1;//排除本身也在那一列中
}
}
//下面类同上方代码
for (it = y.begin(); it != y.end(); ++it)
{
int idx = it->first;
for (it1 = y[idx].begin(); it1 != y[idx].end(); ++it1)
for (it2 = ++it1, --it1; it2 != y[idx].end(); ++it2)
{
int tmp = *it1 + *it2;
if (!(tmp & 1) && x[tmp >> 1].count(idx))
ans += x[tmp >> 1].size() - 1;
}
}
printf("%d", ans);
return 0;
}
WA代码
自己写的就挺复杂的,开了好几个函数···套了三层循环,直接炸·····
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define pre(i,a,b) for(int i=a;i>=b;--i)
#define m(x) memset(x,0,sizeof x)
typedef long long ll;
const int maxn = 1e3+10;
#define PI acos(-1)
int mp[maxn][maxn],n,ans = 0;
void check_y(int x,int y)
{
for(int i=1;i<=n;i++)
{
if(i==x)continue;
if(mp[i][y]){
ans++;
//printf("%d\n",ans);
}
}
}
void check_x(int x,int y)
{
for(int i=1;i<=n;i++)
{
if(i==y)continue;
if(mp[x][i]){
ans++;
//printf("%d\n",ans);
}
}
}
void scan_x(int x)
{
int temp[maxn];
int l,mid,r,k;
l = mid = r = -1;
k = 0;
for(int j=1;j<=n;++j)
if(mp[x][j])temp[k++] = j;
if(k>=3)
{
int index = 0;
l = temp[0];mid = temp[1];r = temp[2];
while(index+3<=k)
{
index ++;
if((mid-l)==(r-mid)){
//printf("%d %d\n",x,mid);
check_y(x, mid);
//printf("%d %d %d\n",l,mid,r);
}
l = temp[index];mid = temp[index+1];r = temp[index+2];
}
}
}
void scan_y(int y)
{
int temp[maxn];
int l,mid,r,k;
l = mid = r = -1;
k = 0;
for(int i=1;i<=n;++i)
if(mp[i][y])temp[k++] = i;
if(k>=3)
{
int index = 0;
l = temp[0];mid = temp[1];r = temp[2];
while(index+3<=k)
{
index ++;
if((mid-l)==(r-mid)){
//printf("%d %d\n",x,mid);
check_x(mid,y);
//printf("%d %d %d\n",l,mid,r);
}
l = temp[index];mid = temp[index+1];r = temp[index+2];
}
}
}
int main()
{
int x,y;
scanf("%d",&n);
int t = n;
rep(i, 0, t-1)
{
scanf("%d%d",&x,&y);
mp[x][y] = 1;
n = max(x,n);
n = max(y,n);
}
//从上到下每行扫描
for(int x=1;x<=n;++x)
scan_x(x);
for(int y=1;y<=n;++y)
{
scan_y(y);
}
printf("%d\n",ans);
return 0;
}