POJ -- 2443 Set Operation 【 二进制压位 】

传送门
题意应该好懂, 就不说了.
思路:将每一个集合看成是一行,也成了一个10000 * 1000 的0、1矩阵,对于每个数来书,它所在的列的0、1分布情况也就是它所在集合的情况。但问题是现在一共有1000行,2^1000肯定不行,但考虑到一个int可以存32位(2^32),1000<32*32,所以可以开32个整数,每个整数的二进制的每一位代表每一行,这样就可以在q*32的可接受的时间复杂度内查询出结果。将扫描1000变为扫描32,利用整数的位操作减少为1/32.
//然后为了直观方便的给出, 所以我用的bitset.
AC Code

/** @Cain*/
#include
const int maxn = 1e4+5;

void solve()
{
    int n;
    scanf("%d",&n);
    bitset<1005> bit[maxn];  //1005代表那些集合, maxn代表那些数的范围,
    //bit[3][5] = 1 说明第5个集合有3这个数.
    for(int i=1;i<=n;i++){
        int k; scanf("%d",&k);
        while(k--){
            int u; scanf("%d",&u);
            bit[u][i] = 1;
        }
    }
    int q;
    scanf("%d",&q);
    while(q--){
        int u,v;
        scanf("%d%d",&u,&v);
        bitset<1005> tmp;   //自动初始化为0.
        if((bit[u] & bit[v]) == tmp){   // & 的优先级比== 更低.
            //如果等于0,就是说明没有在任何一个集合中有相同的元素.
            printf("No\n");
        }
        else
            printf("Yes\n");
    }
}
int main()
{
    int t = 1;
    //cin >> t;
    while(t--){
        solve();
    }
}

你可能感兴趣的:(二进制思维/状压/bitset)