Merge Equals
You are given an array of positive integers. While there are at least two equal elements, we will perform the following operation. We choose the smallest value x x x that occurs in the array 2 2 2 or more times. Take the first two occurrences of x x x in this array (the two leftmost occurrences). Remove the left of these two occurrences, and the right one is replaced by the sum of this two values (that is, 2 ⋅ x 2 \cdot x 2⋅x).
Determine how the array will look after described operations are performed.
For example, consider the given array looks like [ 3 , 4 , 1 , 2 , 2 , 1 , 1 ] [3, 4, 1, 2, 2, 1, 1] [3,4,1,2,2,1,1]. It will be changed in the following way: [ 3 , 4 , 1 , 2 , 2 , 1 , 1 ] → [ 3 , 4 , 2 , 2 , 2 , 1 ] → [ 3 , 4 , 4 , 2 , 1 ] → [ 3 , 8 , 2 , 1 ] [3, 4, 1, 2, 2, 1, 1]~\rightarrow~[3, 4, 2, 2, 2, 1]~\rightarrow~[3, 4, 4, 2, 1]~\rightarrow~[3, 8, 2, 1] [3,4,1,2,2,1,1] → [3,4,2,2,2,1] → [3,4,4,2,1] → [3,8,2,1].
If the given array is look like [ 1 , 1 , 3 , 1 , 1 ] [1, 1, 3, 1, 1] [1,1,3,1,1] it will be changed in the following way: [ 1 , 1 , 3 , 1 , 1 ] → [ 2 , 3 , 1 , 1 ] → [ 2 , 3 , 2 ] → [ 3 , 4 ] [1, 1, 3, 1, 1]~\rightarrow~[2, 3, 1, 1]~\rightarrow~[2, 3, 2]~\rightarrow~[3, 4] [1,1,3,1,1] → [2,3,1,1] → [2,3,2] → [3,4].
Input
The first line contains a single integer n n n ( 2 ≤ n ≤ 150 000 2 \le n \le 150\,000 2≤n≤150000) — the number of elements in the array.
The second line contains a sequence from n n n elements a 1 , a 2 , … , a n a_1, a_2, \dots, a_n a1,a2,…,an ( 1 ≤ a i ≤ 1 0 9 1 \le a_i \le 10^{9} 1≤ai≤109) — the elements of the array.
Output
In the first line print an integer k k k — the number of elements in the array after all the performed operations. In the second line print k k k integers — the elements of the array after all the performed operations.
Example
i n p u t \tt input input |
---|
7 3 4 1 2 2 1 1 |
o u t p u t \tt output output |
4 3 8 2 1 |
i n p u t \tt input input |
---|
5 1 1 3 1 1 |
o u t p u t \tt output output |
2 3 4 |
i n p u t \tt input input |
---|
5 10 40 20 50 30 |
o u t p u t \tt output output |
5 10 40 20 50 30 |
Tutorial
本题就是一个模拟题,但在模拟时需要考虑怎样删除元素
根据题意,相当于两个相同的元素,其中左侧的元素将合并到右侧的那个元素上,等价于左侧的元素变为
0
0
0,右侧的元素变成自己的两倍,所以只需要遍历数组,如果之前出现过相同的数,就将之前出现过的位置置为 0
,自己就变为原来的
2
2
2 倍,直至不能再合并,最后数组中不为 0
的数就是答案
此解法时间复杂度为 O ( n ) \mathcal O(n) O(n)
Solution
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
signed main() {
int n;
cin >> n;
map<int, int> idx;
vector<int> a(n + 1), ans;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
if (idx[a[i]]) {
while (idx[a[i]]) {
a[idx[a[i]]] = 0;
idx.erase(a[i]);
a[i] <<= 1;
}
idx[a[i]] = i;
} else {
idx[a[i]] = i;
}
}
for (int ai : a) {
if (ai) {
ans.emplace_back(ai);
}
}
cout << ans.size() << endl;
for (int ai : ans) {
cout << ai << " \n"[ai == ans.back()];
}
return 0;
}