题目描述
查看题目信息
给定一个正整数序列,这里面至少有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;
}
还有,如果你想运行不出现黄色提醒的话,就要这样改一下语言标准:
第一(点开 "工具" 的 "编译选项 " ):