题目描述:
我们希望一个序列中的元素是各不相同的,但是理想和现实往往是有差距的。现在给出一个序列A,其中难免有些相同的元素,现在提供了一种变化方式,使得经过若干次操作后一定可以得到一个元素各不相同的序列。
这个操作是这样的,令x为序列中最小的有重复的数字,你需要删除序列左数第一个x,并把第二个x替换为2*x。
请你输出最终的序列。
例如原序列是[2,2,1,1,1],一次变换后变为[2,2,2,1],两次变换后变为[4,2,1],变换结束
输入描述
输入第一行包含一个正整数n,表示序列的长度为n。(1<=n<=50000)
第二行有n个整数,初始序列中的元素。(1<=a_i<=10^8)
输出描述
输出包含若干个整数,即最终变换之后的结果。
样例输入
5
5 5 5 5 4
样例输出
20 4
基本思想:
- 将元素保存在链表中,便于从任意位置删除
- 同时将元素保存在优先队列中(使得元素从小到大排列),便于找到最小的元素
- 队列非空时,执行如下循环:
判断队头元素是否是重复元素,如果是则将第一次出现的删掉,将第二次出现的变为2倍,并加入优先队列中。
这里为了便于删除元素,需要用一个变量来保存元素的位置。
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >> n;
list<int> ls;
priority_queue<int, vector<int>, greater<int>> pq;//从小到大
for(int i = 0; i < n; ++i){
//将元素存入链表的同时,存入优先队列中
int t;
cin >> t;
ls.push_back(t);
pq.push(t);
}
while(!pq.empty()){
int val = pq.top();
pq.pop();
//检查该元素是否重复
int cnt = 0;
auto pre = ls.begin();
for(auto iter = ls.begin(); iter != ls.end(); ++iter){
if(*iter == val){
++cnt;
if(cnt > 1){
*iter = *iter * 2;
pq.push(*iter);
ls.erase(pre);
break;
}
pre = iter;//这个语句一定要放在if判断条件之后,目的是保存第一次出现重复元素的位置
}
}
}
for(auto iter = ls.begin(); iter != ls.end(); ++iter){
cout << *iter << " ";
}
return 0;
}