穿过圆(bitset)

这篇博客探讨了一道算法题目,涉及平面上的点和不相交圆。文章介绍了如何使用暴力方法和优化策略(如位运算和压位)来解决从一点到另一点穿越最少圆的问题。优化后的算法大大提高了效率,通过位运算计算两点在各圆内外状态的异或结果,得到穿越圆的数量。此外,文章还提及了利用倍增LCA(最近公共祖先)的解决方案,但未展开详细说明。
摘要由CSDN通过智能技术生成

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
题目链接
穿过园

题目大意
平面上又许多不相交的园包围着点,每回询问两个点 a ,b 询问从a到b至少穿过多少个圆。

思路
最开始想到暴力的解法,也就是对每个点进行遍历,看其是否在园内,并将此点在多少个园内的数量记录在一个数组cnt中,然后记录a和b在相同园内的数量(假设记作k),拿cnt[a]+cnt[b]-2*k即为答案,这样做的时间复杂度过大无法通过题目要求。

听课后学会了一种压位的做法,即用bitset存储这个点对于各个园的状态,在园内为0,在园外为1,然后将两个点的二进制位数亦或,此时二进制中1的个数即为所求答案。
代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <bitset>

#define x first
#define y second

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

const int N = 1010;

int n, m, Q;
PII p[N], c[N];
int r[N];

bitset<N> st[N];

LL sqr(LL x)
{
    return x * x;
}

int check(int a, int b)
{
    LL dx = p[a].x - c[b].x;
    LL dy = p[a].y - c[b].y;
    if (sqr(dx) + sqr(dy) > sqr(r[b])) return 1;
    return 0;
}

int main()
{
    scanf("%d%d%d", &n, &m, &Q);
    for (int i = 1; i <= n; i ++ ) scanf("%d%d", &p[i].x, &p[i].y);
    for (int i = 0; i < m; i ++ )
        scanf("%d%d%d", &r[i], &c[i].x, &c[i].y);

    for (int i = 1; i <= n; i ++ )
        for (int j = 0; j < m; j ++ )
            st[i][j] = check(i, j);

    while (Q -- )
    {
        int a, b;
        scanf("%d%d", &a, &b);
        printf("%d\n", (st[a] ^ st[b]).count());
    }

    return 0;
}

此外此题还有倍增LCA做法 (待补充)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值