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 }