Set Operation POJ - 2443

原题链接

  • 题意:给你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\times 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;
}
posted @ 2021-04-02 11:17  u_yan  阅读(58)  评论(0编辑  收藏  举报