Codeforces 962D - Merge Equals

链接:

http://codeforces.com/problemset/problem/962/D

 

题意:

给出一个整数序列。选择其中最小且出现两次(或以上)的数,把最左边的两个从序列中移除,
然后把它们的和放到它们的后面第一位。不断重复上述过程,直到序列中的每个数都是唯一的。
输出最后的序列。

 

分析:

如果在数a的前面有一个可以跟a合并的数b,则b一定是唯一的。否则,b要先跟其他等值的数合并。
这样,我们只需要从左到右依次加入每个数,不断维护当前序列的唯一性即可。
方法是用map记录前面每个数值的唯一位置,然后当前的数a尽量地跟前面的数合并(注意a是可以不断变化的)。

 

代码:

 1 #include <cstdio>
 2 #include <map>
 3 using namespace std;
 4 
 5 long long a[150000+5];
 6 
 7 int main() {
 8     int n;
 9     map<long long,int> M; // 值为x的唯一数组下标
10     scanf("%d", &n);
11     int ans = n;
12     for(int i = 1; i <= n; i++) {
13         scanf("%lld", &a[i]);
14         while(M[a[i]]) { // 如果前面有值为a[i]的元素,则合并,注意a[i]是变化的
15             a[M[a[i]]] = 0;
16             M[a[i]] = 0;
17             a[i] += a[i];
18             ans--;
19         }
20         M[a[i]] = i;
21     }
22     printf("%d\n", ans);
23     for(int i = 1; i <= n; i++) if(a[i]) printf("%lld ", a[i]);
24     return 0;
25 }

 

posted @ 2018-04-12 20:01  Ctfes  阅读(295)  评论(0编辑  收藏  举报