数集
题目背景:
11.06 NOIP模拟T1
分析:队列
考虑暴力的想法当然是直接维护一个堆,每一次取出最小的一个,然后把2 * x + 1, 3 * x + 1 push进去,但是看看最大数据,1000000还有10组数据,这怕不是要死人······于是乎,认真想正解,然后就发现了,显然,因为每一次取出的数是一次递增的,那么2 * x + 1和3 * x + 1也一定是递增的,也就是说这两个数值都是单调的,有没有很熟悉,没错就是NOIP2016蚯蚓的想法,我们直接维护两个队列,一个是2 * x + 1的队列,一个3 * x + 1的队列,每次取队首较小的一个然后将新的两个数加到队尾即可。
注意:本题需要去重,具体怎么去呢,你想想看如果同一个数有两个,那你第二次取出这个数的时候,一定是你第一次取出之后的那一次······所以直接判断和上一次取出的数是否一样即可。
Source:
/*
created by scarlyw
*/
#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
const int MAXN = 1000000 + 10;
int a, n, cur;
int q[2][MAXN << 1 | 1];
inline void solve() {
if (n == 1) {
std::cout << a << '\n';
return ;
}
int tail1 = 0, tail2 = 0, head1 = 1, head2 = 1, last = a;
q[0][++tail1] = 2 * a + 1, q[1][++tail2] = 3 * a + 1;
for (int i = 2; i <= n; ++i) {
do {
if ((head2 > tail2) || (head1 <= tail1 &&
q[0][head1] <= q[1][head2])) cur = q[0][head1], head1++;
else cur = q[1][head2], head2++;
} while (cur == last);
q[0][++tail1] = cur * 2 + 1, q[1][++tail2] = cur * 3 + 1, last = cur;
}
std::cout << cur << '\n';
}
int main() {
// freopen("blash.in", "r", stdin);
// freopen("blash.out", "w", stdout);
while (~scanf("%d%d", &a, &n)) solve();
return 0;
}