给定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;
}