惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
爱范儿
爱范儿
J
Java Code Geeks
L
LangChain Blog
V
V2EX
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
博客园 - Franky
Microsoft Azure Blog
Microsoft Azure Blog
Jina AI
Jina AI
Blog — PlanetScale
Blog — PlanetScale
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The Cloudflare Blog
博客园 - 司徒正美
B
Blog
G
Google Developers Blog
Stack Overflow Blog
Stack Overflow Blog
罗磊的独立博客
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Apple Machine Learning Research
Apple Machine Learning Research
Engineering at Meta
Engineering at Meta
MyScale Blog
MyScale Blog
有赞技术团队
有赞技术团队
Hugging Face - Blog
Hugging Face - Blog

Ariasakaの小窝

Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝 Ariasakaの小窝
Ariasakaの小窝
2023-07-22 · via Ariasakaの小窝

传送门:

前往以下网站,不保证安全性哦喵~【ABC254Ex】 Multiply or Divide by 2洛谷

题意

给你两个集合 $A$ 和 $B$ ,你可以把集合 $A$ 的任意一项变为原来的 $\left \lfloor\frac{1}{2}\right \rfloor $ 或 $2$ 倍,求至少需要操作几步才能使 $A=B$。如果无法将 $A$ 变为 $B$,输出 -1

解析

考虑贪心,可以将“把 $A$ 的任意元素变为原来的两倍”转换为“把 $B$ 的任意元素变为原来的 $\frac{1}{2}$”,这两个方法是等效的。

我们维护两个优先队列 ab代表集合 $A$ 和 $B$ ,每次取出两个集合的最大值进行转化,然后我们采用这样的贪心策略:

如果 a.top()==b.top() ,那么直接将这两个元素出队,这说明两个集合的这两个元素已经相等了。

如果 b.top()>a.top() ,那么将 b.top() 出队,除以2后再入队,这等价于将 集合 $A$ 的最大值乘上2。

大家应该意识到了一个问题,如果将 b.top() 除以2的话,实际上是和 a.top()*2 的效果并不完全一样,因为除以2时会向下取整,所以到后面会一直多一个 1 而无法将 $A$ 变为 $B$,这种情况就需要输出 -1 了。

接下来如果 a.top()>b.top() 的话,跟上面一样,将 a.top() 出队,除以2后再入队即可,不需要考虑其他条件,因为在题意中已经说到需要向下取整了。

代码

那么代码就很简单了,使用优先队列维护即可,单次修改(除 a.top()==b.top() 时)执行 cnt++,最后输出 cnt 作为答案即可。

注释版

C++
#include <bits/stdc++.h>
using namespace std;
int n,t,cnt; //cnt作为答案 
priority_queue<int> a,b; //优先队列 
int main(){
    ios::sync_with_stdio(0);
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>t,a.push(t); //直接在a和b中入队,不需要静态数组储存,后面用不到静态数组的 
    for(int i=1;i<=n;i++)
        cin>>t,b.push(t);
    while(!a.empty()){
        if(a.top()==b.top()) //贪心策略1,见TJ 
            a.pop(),b.pop();
        else if(a.top()>b.top()){ //贪心策略3,见TJ 
            t=a.top();
            a.pop(),a.push(t>>1),cnt++;
        }
        else if(b.top()>a.top()){ //贪心策略2,见TJ 
            if(b.top()&1) //b.top()是奇数则不满足*2的条件 
                cout<<"-1",exit(0); //退出程序,exit(0)等效于在main中return 0;,但是不用花括号 
            t=b.top(); //需要一个变量临时保存当前的堆顶 
            b.pop(),b.push(t>>1),cnt++; //位运算卡常 x>>1==x/2 
        }
    }
    cout<<cnt;
    return 0; //好习惯 
}

无注释版

可以CTJ的版本

C++
#include <bits/stdc++.h>
using namespace std;
int n,t,cnt;
priority_queue<int> a,b;
int main(){
    ios::sync_with_stdio(0);
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>t,a.push(t);
    for(int i=1;i<=n;i++)
        cin>>t,b.push(t);
    while(!a.empty()){
        if(a.top()==b.top())
            a.pop(),b.pop();
        else if(a.top()>b.top()){
            t=a.top();
            a.pop(),a.push(t>>1),cnt++;
        }
        else if(b.top()>a.top()){
            if(b.top()&1)
                cout<<"-1",exit(0);
            t=b.top();
            b.pop(),b.push(t>>1),cnt++;
        }
    }
    cout<<cnt;
    return 0;
}

multiset做法

我这里提供一种 multiset 的做法,闲的没事写的(

C++
#include <bits/stdc++.h>
using namespace std;
int n,t,cnt;
multiset<int> a,b;
int main(){
    ios::sync_with_stdio(0);
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>t,a.emplace(t); //emplace比insert稍微快一点
    for(int i=1;i<=n;i++)
        cin>>t,b.emplace(t);
    while(!a.empty()){
        if(*a.rbegin()==*b.rbegin())
            a.erase(--a.end()),b.erase(--b.end());
        else if(*a.rbegin()>*b.rbegin()){
            t=*a.rbegin();
            a.erase(--a.end()),a.emplace(t>>1),cnt++;
        }
        else if(*a.rbegin()<*b.rbegin()){
            if((*b.rbegin())&1)
                cout<<"-1",exit(0);
            t=*b.rbegin();
            b.erase(--b.end()),b.emplace(t>>1),cnt++;
        }
    }
    cout<<cnt;
    return 0;
}

【ABC254Ex】 Multiply or Divide by 2 题解