【POJ 2443】Set Operation 题解(位集合)

给定N个集合,第i个集合(用S(i)表示)有C(i)元素(这里的“集合”与数学中定义的“集合“并不完全相同,一个集合可能包含两个相同的元素)。集合中的每个元素都用1到10000之间的正数表示。现在有一些问题需要回答。查询是为了确定两个给定的元素i和j是否同时属于至少一个集合。换句话说,你应该确定是否存在一个数k(1<=k<=N),使得元素i属于S(k),元素j也属于S(k)。

输入
输入的第一行包含一个整数N(1<=N<=1000),它表示集合的数量。然后按照N行。每个数字都以一个数字C(i)开始(1<=C(i)<=10000),然后用空格分隔的C(i)个数字紧随其后,给出集合中的元素(这些C(i)个数字不必彼此不同)。N+2行包含一个数字Q(1<=Q<=200000),表示查询的数量。然后按照Q线。每个包含一对数字i和j(1<=i,j<=10000,i可以等于j),它们描述了需要回答的元素。
输出
对于每个查询,在一行中,如果存在这样的数字k,则打印“是”;否则打印“否”。

Sample
Input
3
3 1 2 3
3 1 2 5
1 10
4
1 3
1 5
3 5
1 10
Output
Yes
Yes
No
No

暗示
输入可能很大,并且C++语言的I/O函数(cin/cout)对于这个问题可能有点太慢。

思路

输入可能很大,进行读入优化。用位集合记录该数字所属的集合。比较两个数时,对这两个数对应的位集合进行逻辑与运算,统计1的数目。若1的数目不为0则说明这两个数同时属于至少一个集合,输出Yes,否则输出No。

AC代码

#include <iostream>
#include <bitset>
#define AUTHOR "HEX9CF"
using namespace std;

void read(int &x)
{
    char ch = getchar();
    x = 0;
    for (; ch < '0' || ch > '9'; ch = getchar())
    {
    }
    for (; ch >= '0' && ch <= '9'; ch = getchar())
    {
        x = x * 10 + ch - '0';
    }
}

int main()
{
    int n, q;
    bitset<1010> Bs[10100];
    // cin >> n;
    read(n);
    for (int i = 0; i < n; i++)
    {
        int c;
        // cin >> c;
        read(c);
        for (int j = 0; j < c; j++)
        {
            int t;
            // cin >> t;
            read(t);
            Bs[t][i] = 1;
        }
    }
    cin >> q;
    // cout << n << " " << q << endl;
    for (int i = 0; i < q; i++)
    {
        int a, b;
        // cin >> a >> b;
        read(a), read(b);
        if ((Bs[a] & Bs[b]).count())
        {
            cout << "Yes" << endl;
        }
        else
        {
            cout << "No" << endl;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值