Merge Equals 题解

题目描述

查看题目信息

给定一个正整数序列,这里面至少有2个数相同。

我们执行如下操作:找到最小的数值x(x重复出现了2次或2次以上),删除第1次出现的x,将第2次出现的x改为2*x(数值在原来基础上乘以2),直到序列中没有哪个数值重复出现2次或2次以上。

比如:给定序列[3,4,1,2,2,1,1].将按如下方式进行变化:[3,4,1,2,2,1,1]->[3,4,2,2,2,1]->[3,4,4,2,1]->[3,8,2,1]

输入格式

第1行包含一个正整数n(2<=n<=150000),表示序列中元素的个数。

第2行包含n个正整数a1,a2,...,an(1<=ai<=10^9)

输出格式

第一行打印一个整数k,表示序列最终形态所包含元素的个数。

第2行打印k个整数,表示序列的最终形态

样例输入1

7 
3 4 1 2 2 1 1

样例输出1

4 
3 8 2 1

样例输入2

5
10 40 20 50 30

样例输出2

5
10 40 20 50 30 

样例输入3

5
1 1 3 1 1

样例输出3

2
3 4 

这道题我们找到最小的数值x(x重复出现了2次或2次以上),删除第1次出现的x,将第2次出现的x改为2*x

3 4 1 2 2 1 1

3 4 0 2 2 2 1

3 4 0 0 4 2 1

3 0 0 0 8 2 0

·找最值(删除)优先队列

        ·值越小优先级越高,相同,原序列中越靠前,优先级越高

这道题的思路:

把所有元素放同一个优先队列中

·值越小,优先级越高

·相同,位置越靠前,优先级越高

每次取出两了元素

·相同:删除第一个,增大第二个,放回第二个

·不同:舍弃第一个,放回第二个

代码是这样写的:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node
{
	int id;
	ll x;
	friend bool operator <(node a,node b)
	{
		if(a.x!=b.x) return a.x>b.x;//值越小,优先级越高 
		return a.id>b.id;//值相同,越靠前,优先级越高 
	}
};
priority_queue<node> q;
ll a[150005];
int main()
{
	int n,cnt=0;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		q.push(node{i,a[i]});
	}
	while(!q.empty())
	{//每次取出两个元素 
		node x1=q.top();q.pop();
		if(q.empty()) break;
		node x2=q.top();q.pop();
		if(x1.x==x2.x)//相同 
		{
			a[x1.id]=0;//删除第一个数 
			cnt++;//计数 
			a[x2.id]*=2;//第二个数变成两倍 
			x2.x=a[x2.id];
			q.push(x2);//放回第二个数 
		}
		else//不同 
		{
			q.push(x2);//放回第二个 
		}
	}
	cout<<n-cnt<<endl;//输出剩余 
	for(int i=1;i<=n;i++){//按原来顺序依次输出剩下的 
		if(a[i]){
			cout<<a[i]<<" ";
		}
	}
	return 0;
}

还有,如果你想运行不出现黄色提醒的话,就要这样改一下语言标准:

第一(点开 "工具" 的 "编译选项 " ):

 第二(把 "语言标准(-std)" 的后面改成 GNU C++11 ):

 这样就不会出现黄色警告啦

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值