CF1839C题解
-
分析
首先对于最后一个元素为1的数组,显然不存在合法构造方式。为什么?因为每个1都需要至少一个数插入在它后面对它完成翻转,如果最后一个数为1,这时没有数在它后面翻转它,所以这时无法构造。
然后我们很naive地想让每个1都只被翻转一次,那么很好想到,对于一个形如\(11\dots100\dots0\)的数组,只需要先插0然后最后一步在最后一个1后面的位置插一个0将前面全翻过来就行。
那么如果这个数组前面有一个全0字符串,那么最后加几个0就行。
如果这个数组前面有一个10字符串,那么我们先输出后面的,再输出前面的就行。那么所有合法数组都能转化成(全0字符串+)若干10字符串组合的形式(前面如果有全1字符串会合并到第一个10串中),只需要从后向前输出每个10串的构造方式,如果最前面存在全0字符串最后还要输出几个0。
-
代码
#include <iostream>
using namespace std;
constexpr int MAXN(1000007);
int a[MAXN], ans[MAXN];
int T, n, lst, cb;
inline void read(int &temp) { cin >> temp; }
inline void work() {
read(n);
for (int i(1); i <= n; ++i) read(a[i]), ans[i] = 0;
if (a[n]) return cout << "NO" << endl, void();
cout << "YES" << endl;
lst = n;
for (int i(n); ~i; --i) {
if (a[i]) ++cb;
if (!a[i] && cb) {
for (int j(i + 1); j < lst; ++j) cout << "0 ";
cout << cb << " ";
cb = 0, lst = i;
}
}
for (int i(1); i <= lst; ++i) cout << "0 ";
cout << endl;
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
read(T);
while (T--) work();
return 0;
}