2019CCPC秦皇岛A

本文讲述了作者在训练赛中遇到的代码性能问题,原本使用map导致了时间超限(TLE),后来通过将map替换为unordered_map成功解决了问题。文章强调了读题的重要性,并分享了如何针对直角点和非直角点进行询问的解决方案,同时提供了AC代码,展示了预处理斜率信息和使用hash技巧来提高查询效率。
摘要由CSDN通过智能技术生成

昨天训练赛打了重现赛 ,我卡了好久A,队友又卡了F,直接血崩。

调了一整天A,昨天还以为被__gcd卡了,结果是被map卡常,真是太草了。今天把昨天TLE的代码map改成了hash+unordered_map就过了。

反思:读题仍是我们队最大的问题,应该尽可能每句话都看清。觉得可以写的题可以尝试,但是应该尽量跟榜。

题解:分成询问点是直角点和非直角点考虑。利用map<pair<ll,ll>>存储无精度问题的斜率信息。但是map太慢了,并且我的写法用不到map的自动排序功能,因此可以用hash映射坐标、unordered_map提高插入/查询速度。

AC代码:

inline long long gethash(ll x, ll y)
{
    return x * 2333 + y * 23333 + 100000007;
}
unordered_map<long long, int> mp;
unordered_map<long long, int> mp2[100010];
int x[2010];
int y[2010];
int main()
{
    int n, q;
    scanf("%d%d", &n, &q);
    for (int i = 1; i <= n; i++)
        scanf("%d %d", &x[i], &y[i]);
    for (int i = 1; i <= n; i++) //预处理所有斜率
    {
        for (int j = 1; j <= n; j++)
        {
            if (i == j)
                continue;
            int x1 = x[i] - x[j];
            int y1 = y[i] - y[j];
            if (!x1)
            {
                mp2[i][INF]++;
                mp2[j][INF]++;
            }
            else if (!y1)
            {
                mp2[i][0]++;
                mp2[j][0]++;
            }
            else
            {
                int g = __gcd(x1, y1);
                x1 /= g;
                y1 /= g;
                mp2[i][gethash(x1, y1)]++;
                mp2[j][gethash(x1, y1)]++;
            }
        }
    }

    for (int i = 1; i <= q; i++)
    {
        int xx, yy;
        scanf("%d %d", &xx, &yy);
        mp.clear();
        long long ans = 0;
        for (int j = 1; j <= n; j++) //查询点是直角点
        {
            if (x[j] == xx && y[j] == yy)
                continue;
            if (xx - x[j] == 0)
            {
                mp[INF]++;
                if (mp.count(0))
                    ans += mp[0];
            }
            else if (yy - y[j] == 0)
            {
                mp[(0)]++;
                if (mp.count(INF))
                    ans += mp[INF];
            }
            else
            {
                int x1 = xx - x[j];
                int y1 = yy - y[j];
                int g = __gcd(x1, y1);
                x1 /= g;
                y1 /= g;
                mp[gethash(x1, y1)]++;
                if (mp.count(gethash(-y1, x1)))
                    ans += mp[gethash(-y1, x1)];
                if (mp.count(gethash(y1, -x1)))
                    ans += mp[gethash(y1, -x1)];
            }
        }
        for (int j = 1; j <= n; j++) //查询点是非直角点
        {
            int x1 = xx - x[j];
            int y1 = yy - y[j];
            if (x[j] == xx && y[j] == yy)
                continue;
            if (!x1)
            {
                if (mp2[j].count(0))
                    ans += mp2[j][0] / 2;
            }
            else if (!y1)
            {
                if (mp2[j].count(INF))
                    ans += mp2[j][INF] / 2;
            }
            else
            {
                int g = __gcd(x1, y1);
                x1 /= g;
                y1 /= g;
                if (mp2[j].count(gethash(-y1, x1)))
                    ans += mp2[j][gethash(-y1, x1)] / 2;
                if (mp2[j].count(gethash(y1, -x1)))
                    ans += mp2[j][gethash(y1, -x1)] / 2;
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hesorchen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值