原题链接
- 题意:给你N个集合,第i个集合S[i]有C[i]个元素(注意此处集合并非C++的set,而是允许存在两个相同元素)。每个元素为1到10000之间的整数。接着给你几个问题。对于每个问题给出的元素i,j,你要判断它们是否同时属于一个集合。换句话说,是否存在k(1<=k<=N)可以使i和j均存在与S[k]中。(1<=N<=1000,1<=Q<=200000)
- 题解:显然的想法是用 (bitset) 存下每个组有哪些元素,然后每次询问暴力遍历一遍组,是否是在一个组里,复杂度是 (O(N imes Q)) 的复杂度,吃得不是很消。神奇的方法是,记录元素都在哪些组里,然后就可以 (&) 一下,看看是否有 (1) 存在,如果有 (1) 存在,那么必然会在同一组中。复杂度即为 (O(Q))。用到了 (bit.any()) 函数,当有 (1) 存在返回 (1),否则返回 (0)。
- 代码:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <bitset>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
const ll N = 100009;
ll mod = 1e9 + 7;
const ll maxn = 110;
bitset<1009> bit[10009];
inline ll rd() {
ll x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + (ch ^ 48); //二进制向左移动三位+向左移动1位,x*2*2*2+x*2
//= x*10, ch^48 = ch'0'
ch = getchar();
}
return x * f;
}
void solve() {
ll n;
n = rd();
for (int i = 1; i <=n; i ++) {
ll cnt;
cnt = rd();
while (cnt--) {
ll x;
x = rd();
bit[x].set(i);
}
}
ll q;
q = rd();
while (q--) {
ll l, r;
l = rd();
r = rd();
bool f = 0;
bitset<1009> t;
t = bit[l] & bit[r];
if (!(t.any()))puts("No");
else puts("Yes");
}
}
signed main() {
ll t = 1;//cin >> t;
while (t--) solve();
return 0;
}