【模拟】 直角三角形

题目描述

平面上给定N个两两不同的整点,统计以给定的点为顶点,且直角边平行于坐标轴的直角三角形数。

输入输出格式

输入格式:

输入文件right.in第一行为一个整数N

以下N行,每行给出一个点的坐标。

输出格式:

输出文件名为right.out。输出一个整数表示统计结果。

输入输出样例

输入样例#1:

4

0 0

0 1

1 0

1 1

输出样例#1:
4

说明

30%的数据满足 N ≤ 100;

50%的数据满足 N ≤ 1000;

100%的数据满足0 < N ≤100000,所有坐标不超过32位整数范围。


分析

纯模拟题 真的很简单 但是我只得了90分 有一个点WA了 现在还不知道为什么……

说一下思路:

对于每一个点  一个与它横坐标相同的点与一个与它纵坐标相同的点能与它形成一个满足题意的三角形

所以对于这一个点来说 我们可以将与它横坐标相同的点的个数与纵坐标相同的点的个数相乘,即使这个点构成的三角形个数

将每个点的这样的个数相加  最后的和即是我们要求得的答案

然而每个点每个点暴力去找与它横坐标或纵坐标相同的点……当然会很慢

所以我们先sort一下再进行计算

#include<algorithm>
#include<iostream>
#include<cstdio>
#define MAXN 100005
using namespace std;
struct Point
{
    int x;
    int y;
    int ansx,ansy;//ansx ansy记录与这个点横坐标或纵坐标相同的点的个数
} p[MAXN];
bool cmp1(const Point &a,const Point &b)//对点的横坐标排序
{
    return a.x<b.x;
}
bool cmp2(const Point &a,const Point &b)//对点的纵坐标排序
{
    return a.y<b.y;
}
int n,t;
long long ans;
int main()
{
    //freopen("right.in","r",stdin);
    //freopen("right.out","w",stdout);
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
        scanf("%d%d",&p[i].x,&p[i].y);
    sort(p+1,p+1+n,cmp1);//将点的横坐标从小到大排序
    t=1;
    while(t<=n)//从左往右循环
    {
        int s=0,r=0;//当前查找坐标为r s为查找的起点
        if(t==n) break;
        int cnt=0;//cnt记录与之坐标相同的点的个数
        s=t;//将起点设为上一次查找的终点
        r=p[t].x;
        while(p[t].x==r)//当当前点的坐标等于正在寻找的坐标时 t++ cnt++
        {
            t++;
            cnt++;
        }
        for(int i=s; i<=t; i++)//与之相同的点的个数为cnt-1
            p[i].ansx=cnt-1;
    }
    sort(p+1,p+1+n,cmp2);//对于纵坐标 与横坐标同理
    t=1;
    while(t<=n)
    {
        int s=0,r=0;
        if(t==n) break;
        int cnt=0;
        s=t;
        r=p[t].y;
        while(p[t].y==r)
        {
            t++;
            cnt++;
        }
        for(int i=s; i<=t; i++)
            p[i].ansy=cnt-1;
    }
    for(int i=1; i<=n; i++)
        ans+=p[i].ansx*p[i].ansy;//答案等于每个点的ansx*ansy的总和
    printf("%d",ans);
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值