题意:给定一个 01 序列 ,对
区间分别进行递增排序,得到
个序列,现给定
序列,
,即所有序列第
位的和。求给定
序列所对应的原序列
。保证原序列
一定存在。
题解: 观察发现对于不同的排序中 1 的数量不会改变,所以 就是原序列中 1 的数量。
对于最后一个 ,即
,发现若
等于
,则
一定等于
,原因如下:该数为序列末尾数,排列方式为递增排列,所以末尾位置上的
不论如何都不会离开,所以总贡献为
。现考虑如果将第
个数字移除所得到的
序列与原
序列的变化。移走一个数,序列数量 -1,并且移走的序列一定是递增序列,因为它是对
区间进行递增排序。当前序列中共有
个 1,那么就需要对
序列在
区间内每个数字-1。这个操作用树状数组优化。区间修改,维护差分数组。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5+10;
int t[N], n;
void modify(int x, int c) {
while(x <= n) {
t[x] += c; x += (x&-x);
}
}
int query(int x) {
int res = 0;
while(x) {
res += t[x]; x -= (x&-x);
}
return res;
}
void slv() {
int num_one = 0, cnt = 0;
cin >> n;
for(int i=1; i<=n; i++) t[i] = 0;
vector<int> c(n + 1);
for(int i=1; i<=n; i++) {
cin >> c[i];
num_one += c[i];
modify(i, c[i] - c[i - 1]);
}
num_one /= n;
for(int i=n; i>=1; i--) {
if(query(i) >= i) {
c[i] = 1;
modify(i - num_one + 1, -1);
modify(i + 1, 1);
num_one --;
} else c[i] = 0;
}
for(int i=1; i<=n; i++) cout << c[i] << ' ';
cout << '\n';
}
signed main() {
cin.tie(nullptr)->sync_with_stdio(false);
int _; cin >> _;
while(_--)
slv();
}