Educational Codeforces Round 42 D. Merge Equals

Merge Equals

time limit per test: 2 second
memory limit per test: 256 megabytes
input: standard input
output: standard output

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 2x).

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 2n150000) — 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} 1ai109) — 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值