CF 1654C Alice and the Cake(模拟)

本文最后更新于:3 years ago

题目链接:点击跳转

题意: 爱丽丝有一块蛋糕,她要把蛋糕切成n份,每一次操作,她会选择一块蛋糕(另大小为A),将其切成两半,两块大小分别为A / 2, (A + 1) / 2,及分成整数的两半,如果原大小为奇数,则一块会大1,现在给出一个序列,问有没有可能为一块蛋糕经过n - 1次操作后得到的

思路: 由每一块拼回去会因为有不同的拼接操作无法判断,可以逆向思维,模拟一块完整的蛋糕切成现在的大小序列,通过维护两个最大堆,如果模拟的堆顶小于该序列,说明无法切出这个序列,输出NO,如果等于,说明序列中的一个元素已经得到,将两个堆顶元素都弹出,如果大于,说明还需要切的更小,将切完的结果压回堆中,如果数组弹空了,说明可以切出该序列,输出YES.

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include<bits/stdc++.h>
#include <ostream>

using namespace std;
typedef long long ll;
#define endl '\n'
typedef pair<int, int> PII;
#define debug() cout.flush()
#define for0(i, a) for (ll i = 0; i < a; ++i)
#define REP(i, a, b) for (ll i = a; i < b; ++i)
#define RREP(i, a, b) for (int i = a; i >= b; --i)
const ll MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int MAXN = 2e5 + 5e2;

inline void init() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}

inline void solve() {
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
priority_queue<ll> q, p;
ll tot = 0;
for0 (i, n) {
ll a;
cin >> a;
tot += a;
q.push(a);
}
bool f = true;
p.push(tot);
while (!q.empty()) {
ll qt = q.top();
q.pop();
ll pt = p.top();
p.pop();
if (qt != pt) {
if (qt > pt) {
f = false;
break;
} else {
q.push(qt);
p.push(pt >> 1);
p.push(pt + 1 >> 1);
}
}
}
cout << (f ? "YES" : "NO") << endl;
}
}

signed main() {
init();
solve();
return 0;
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!