Codeforces Round 843 (Div. 2) B. Gardener and the Array (构造)

原题地址


The gardener Kazimir Kazimirovich has an array of n n n integers c 1 , c 2 , … , c n c_1, c_2, \dots, c_n c1,c2,,cn.

He wants to check if there are two different subsequences a a a and b b b of the original array, for which f ( a ) = f ( b ) f(a) = f(b) f(a)=f(b), where f ( x ) f(x) f(x) is the bitwise OR of all of the numbers in the sequence x x x.

A sequence q q q is a subsequence of p p p if q q q can be obtained from p p p by deleting several (possibly none or all) elements.

Two subsequences are considered different if the sets of indexes of their elements in the original sequence are different, that is, the values of the elements are not considered when comparing the subsequences.

在这里插入图片描述
Input

Each test contains multiple test cases. The first line contains the number of test cases t t t ( 1 ≤ t ≤ 1 0 5 1 \le t \le 10^5 1t105). The description of the test cases follows.

The first line of each test case contains one integer n n n ( 1 ≤ n ≤ 1 0 5 1 \le n \le 10^5 1n105) — the size of the array c c c.

The description of the array c c c in this problem is given implicitly to speed up input.

The ( i + 1 ) (i + 1) (i+1)-st of the following n n n lines of the test case begins with an integer k i k_i ki ( 1 ≤ k i ≤ 1 0 5 1 \le k_i \le 10^5 1ki105) — the number of set bits in the number c i c_i ci. Next follow k i k_i ki distinct integers p i , 1 , p i , 2 , … , p i , k i p_{i, 1}, p_{i, 2}, \dots, p_{i, k_i} pi,1,pi,2,,pi,ki ( 1 ≤ p i ≤ 2 ⋅ 1 0 5 1 \le p_i \le 2 \cdot 10^5 1pi2105) —the numbers of bits that are set to one in number c i c_i ci. In other words, c i = 2 p i , 1 + 2 p i , 2 + … + 2 p i , k i c_i = 2^{p_{i, 1}} + 2^{p_{i, 2}} + \ldots + 2^{p_{i, k_i}} ci=2pi,1+2pi,2++2pi,ki.

It is guaranteed that the total sum of k i k_i ki in all tests does not exceed 1 0 5 10^5 105.

Output

For each set of input, print “Yes” if there exist two different subsequences for which f ( a ) = f ( b ) f(a) = f(b) f(a)=f(b), and “No” otherwise.

You can output the answer in any case (upper or lower). For example, the strings “yEs”, “yes”, “Yes”, and “YES” will be recognized as positive responses.


在这里我们想要去找是否有任何的子序列A或者B,使得 f ( A ) = f ( B ) f(A) = f(B) f(A)=f(B) 得到满足。
那么我们不妨先设A和B序列包含C数组的所有元素,那么这时候一定是满足 f ( A ) = f ( B ) f(A) = f(B) f(A)=f(B) 的(A和B的元素完全一致,或运算之后的结果也完全一致)。

但是题目给出的要求是 A ≠ B A \neq B A=B,所以这时候就去想:如果我们能够从C数组中抽离一个元素,然后将B序列变为抽离一个元素之后的C数组,那么这时候如果仍然满足 f ( A ) = f ( B ) f(A) = f(B) f(A)=f(B),那么就一定是满足题目的条件了。

那么在什么情况下能够做到去掉一个元素之后仍然能够得到相同的或运算结果呢 ?
当然是满足:删掉的元素所包含的二进制数位并不是当前删掉的元素特有的,也就是说删掉的这个元素的二进制形式上的每一个出现1的数位,其他的数也有,这样就不会影响或运算的结果了。

这时候就会有一个疑问,我们这种情况只是取得了一个长度为n的子序列和一个长度为n-1的子序列,仅仅判断这种情况是否能够涵盖所有的情况呢 ?

如果在其他情况下(即没有一种子序列取到了全部元素的情况下)存在 f ( A ) = f ( B ) f(A) = f(B) f(A)=f(B) 并且保证 A ≠ B A \neq B A=B,我们现在使得 A A A 序列更长,因为这时候二者的或运算的结果是完全相同的,如果我们让A和B序列同时再添加上A对于C的补集,或者说添加上 A A A 剩下的没有添加上的 C C C 中的元素,这样就能够使得 A A A 的长度变为 n n n这时候如果B的长度已经变为了 n − 1 n-1 n1,那么就完全转化为了第一种情况。

如果这时候 B B B 的长度不为 n − 1 n-1 n1,这时候就要想,这时候 A A A 的长度为 n n n,也就是说 A A A 包含了所有的 C C C 的元素,是 C C C 中所有元素的或运算的结果,而 f ( B ) f(B) f(B) 是等于 f ( A ) f(A) f(A) 的,那么就说明 B B B 就算再添加上剩下的没有添加上的 C C C 中的任何元素,也都可以保证结果是和 f ( A ) f(A) f(A) 相同,这样就可以让B任意的选取直到长度为 n − 1 n-1 n1,这样就又转化为了第一种情况。

综上所述,我们只需要保证 A A A 序列的长度为 n n n(包含 C C C 中所有元素), B B B 序列的长度为 n − 1 n-1 n1 的情况下存在 f ( A ) = f ( B ) f(A) = f(B) f(A)=f(B) 就可以了。
要使得这种情况得以成立,就只需要保证 C C C 中存在任何一个元素,这个元素的二进制形式出现1的位置,别的数也都出现过就可以了。

CODE:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;

void solve(){
    int n;cin >> n;
    unordered_map<int,int>vis;
    vector<vector<int>>bits(n); //直接开输入的n的大小的,开大了会TLE

    for(int i = 0;i < n;i++){
        int k;cin >> k;
        for(int j = 0;j < k;j++){
            int p;cin >> p;
            bits[i].push_back(p);
            vis[p]++;
        }
    }

    bool flag;
    for(int i = 0;i < n;i++){
        flag = 1;
        for(auto b : bits[i]){
            if(vis[b] == 1){
                flag = 0;
                break;
            }
        }

        if(flag){
            cout << "YES\n";
            return;
        }
    }
    cout << "NO\n";
}

int main(){
    int T;cin >> T;
    while(T--){
        solve();
    }
    return 0;
}

小声1313
去网上找了好多题解都没有办法看的很明白,大多都是因为证明不完全或者是跳了很多步,对于我这种菜狗而言真是难难又受受啊。

  • 35
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值