Codeforces Round #805 (Div. 3)。F. Equate Multisets

 

翻译:

Multiset -是一组数字,其中可以有相等的元素,数字的顺序不重要。当每个值出现相同次数时,两个多重集相等。例如,多集{2,2,4}和{2,4,2}是相等的,但多集{1,2,2}和{1,1,2}-是不相等的。

给出两个多集𝑎和𝑏,每个多集由𝑛整数组成。

在单个操作中,𝑏多集的任何元素都可以被翻倍或减半(向下舍入)。换句话说,对于𝑏多集的元素𝑥,您可以使用以下操作之一:

将𝑥用𝑥⋅2,
或者将𝑥替换为⌊𝑥2⌋(向下舍入)。
注意,不能更改𝑎多集的元素。

看看是否可以在任意数量的操作(可能是0)中使多集𝑏等于多集𝑎。

例如,如果𝑛= 4,𝑎={4、24日5、2},𝑏={4、1、6、11},那么答案是肯定的。我们可以按以下步骤进行:

* 1 * 2=2。我们得到𝑏={4,2,6,11}。
将11替换为⌊112⌋=5。我们得到𝑏={4,2,6,5}。
带6带2=12。我们得到𝑏={4,2,12,5}。
用12⋅2=24替换12。我们得到𝑏={4,2,24,5}。
得到平等的多重集𝑎={4、24日5、2}和𝑏={5}4,2,24日。
输入
输入数据的第一行包含一个整数𝑡(1≤𝑡≤104)——测试用例的数量。

每个测试用例由三行组成。

测试用例的第一行包含一个整数𝑛(1≤𝑛≤2⋅105)——即多重集𝑎和𝑏中的元素数量。

第二行告诉𝑛整数:𝑎1𝑎2,…,𝑎𝑛(1≤𝑎1≤𝑎2≤⋯≤𝑎𝑛≤109)——多重集的元素𝑎。注意,元素可以相等。

第三行包含𝑛整数:𝑏1𝑏2,…,𝑏𝑛(1≤𝑏1≤𝑏2≤⋯≤𝑏𝑛≤109)——多重集的元素𝑏。注意,元素可以相等。

保证所有测试用例的𝑛值的总和不超过2⋅105。

输出
对于每个测试用例,打印在单独的一行上:

是的,如果你能使多集𝑏等于𝑎,
没有否则。
您可以在任何情况下输出YES和NO(例如,字符串YES, YES, YES和YES将被识别为肯定答案)。

例子
inputCopy
5
4
24 5 24
1 4 6 11
3.
1 4 17
4 5 31
5
4 7 10 13 14
2 14 14 26 42
5
2 2 4 4 4 4
28 46 62 71 98
6
1 2 10 16 64 80
20 43 60 74 85 99
outputCopy
是的
没有
是的
是的
是的
请注意
第一个例子在声明中解释了。

在第二个示例中,不可能通过可用的操作从多集𝑏的数字中获得值31。

在第三个例子中,我们可以按照以下步骤进行:

* 2 * 2=4。得到𝑏={4,14,14,26,42}。
将14替换为⌊142⌋=7。我们得到𝑏={4,7,14,26,42}。
将26替换为⌊262⌋=13。我们得到𝑏={4,7,14,13,42}。
将42替换为⌊422⌋=21。我们得到𝑏={4,7,14,13,21}。
将21替换为⌊212⌋=10。我们得到𝑏={4,7,14,13,10}。
得到平等的多重集𝑎={4、7、10、13、14}和𝑏={10}4、7、14日13日。

思路:b进行变换,a不变,b可以乘2,以及/2(向下去整),所以b乘2和a匹配是,a

必是偶数,所以我们可以直接将是偶数的a一直/2,这样b就不用乘2了,然后只剩下/2的操作,因为是大变小,所以我们直接用优先队列来写,从大的开始算,如果b>a,那么就push(b/2),如果相同的话,就a.pop,最后判断即可。

代码:

#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
#include<stack>
using namespace::std;
typedef long long  ll;
int n,t;
inline __int128 read(){
    __int128 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 * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
inline void print(__int128 x){
    if(x < 0){
        putchar('-');
        x = -x;
    }
    if(x > 9)
        print(x / 10);
    putchar(x % 10 + '0');
}

ll ds;
ll jk,kl;
void solv(){
    priority_queue<ll>q;
    priority_queue<ll>w;
    cin>>n;
    for (int i =1; i<=n; i++) {
        cin>>ds;
        while (ds%2==0) {
            ds/=2;
        }
        q.push(ds);
    }
    for (int i =1; i<=n; i++) {
        cin>>ds;
        w.push(ds);
    }
    while (!w.empty()) {
        jk=w.top();w.pop();
        kl=q.top();
        if (jk==kl) {
            q.pop();
        }
        if (jk>kl) {
            w.push(jk/2);
        }
        if (kl>jk) {
            printf("NO\n");return;
        }
    }
    if (q.empty()) {
        printf("YES\n");return;
    }
    printf("NO\n");
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(); cout.tie();
    cin>>t;
    while (t--) {
        solv();
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值