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 }

原文地址:https://www.cnblogs.com/hkxy125/p/8808290.html

时间: 2024-10-19 04:13:07

Codeforces 962D - Merge Equals的相关文章

Educational Codeforces Round 42 (Rated for Div. 2) D - Merge Equals

这道题我可以直接模拟 理由是一个数*2的过程中最多30次左右 2^31 = 2e9 所以我可以从小的书开始模拟这个过程 #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <map> #include <vector> #include <set> typedef long long ll; const

Educational Codeforces Round 42 D. Merge Equals (set + pll)

CF962D 题意: 给定一个数列,对于靠近左端的两个相同大小的值x可以合并成一个点.把x 乘以2 放在第二个点的位置,问最后的数列大小和每个位子的值. 思路: 利用set 配上 pair 就行了,感觉很巧妙,每次取出前两个pll  t1,t2. 如果 t1.first != t2.first ,把t2直接重新放入set中,否则,把t2.first * 2并更新t2.second 位子,把t2放入到set中.(这么说好像优先队列也可以) #include <iostream> #include

Codeforces 1176B - Merge it!

题目链接:http://codeforces.com/problemset/problem/1176/B 题意:给定序列,任意俩个元素可以相加成一个元素,求序列元素能被3整除的最大数量. 思路: 对于所有元素进行 模3 的预处理,然后 看代码吧 AC代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 int t; 6 int a[105]; 7 cin >> t; 8 while(t--)

codeforces 522D. Closest Equals 线段树+离线

题目链接 n个数m个询问, 每次询问输出给定区间中任意两个相同的数的最近距离. 先将询问读进来, 然后按r从小到大排序, 将n个数按顺序插入, 并用map统计之前是否出现过, 如果出现过, 就更新线段树. 如果当前的i等于某个询问的r, 那么就查询, 具体看代码. 1 #include <iostream> 2 #include <vector> 3 #include <cstdio> 4 #include <cstring> 5 #include <

Codeforces 522D Closest Equals

题解: 傻逼题 直接从左向右扫描每个点作为右端点 然后单点修改区间查询就行了 另外一种更直观的做法就是$(i,j)$之间产生了$(j-i)$ 于是变成矩形查最大值,kd-tree维护 代码: #include <bits/stdc++.h> #define rint register int #define IL inline #define rep(i,h,t) for (int i=h;i<=t;i++) #define dep(i,t,h) for (int i=t;i>=h

$Codeforces\ 522D\ Closest\ Equals$ 线段树

正解:线段树 解题报告: 传送门$QwQ$ 题目大意是说给定一个数列,然后有若干次询问,每次询问一个区间内相同数字之间距离最近是多少$QwQ$.如果不存在相同数字输出-1就成$QwQ$ 考虑先预处理出每个点的$pre$和$lst$,就前一个相同数字的位置和后一个相同数字的位置$QwQ$,然后在线段树上维护下每个点到达前一个相同数字的最短距离 然后对询问按左端点排序,每次查询右端点区间内的$min$就成,然后删去数的话就把它后一个数字的那个最短距离$update$成$inf$就成鸭$QwQ$ 然后

AngularJS的核心对象angular上的方法全面解析(AngularJS全局API)

总结一下AngularJS的核心对象angular上的方法,也帮助自己学习一下平时工作中没怎么用到的方法,看能不能提高开发效率.我当前使用的Angularjs版本是1.5.5也是目前最新的稳定版本,不过在全局API上,版本不同也没什么区别. AngularJS 全局 API列表 element bootstrap copy extend merge equals forEach noop bind toJson fromJson identity isUndefined isDefined is

CodeForces A or B Equals C

A or B Equals C Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Description standard input/outputStatements Rami went back from school and he had an easy homework about bitwise operations (and,or,..) The homework was like

Codeforces 847B - Preparing for Merge Sort

847B - Preparing for Merge Sort 思路:前面的排序的最后一个一定大于后面的排序的最后一个.所以判断要不要开始新的排序只要拿当前值和上一个排序最后一个比较就可以了. 代码: #include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int N=2e5+5; int