CF Round #782 D - Reverse Sort Sum
D - Reverse Sort Sum
线段树 / 树状数组
从后往前遍历,如果 c[i] = i, 则说明第 i 个位置上的 1 是从时刻1到 时刻 i 都存在的,所以这一位最开始就是 1,此时若前 i 位有 k 个 1,它们一定在 [i - k + 1, i] 位置上,这个区间 - 1,这是第 i 位的 1 被永远留在这一位了,所以 k--;
否则 k 不减 1,其余操作一样
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int n;
int c[N], tr[N];
int ans[N];
int lowbit(int x)
{
return x & -x;
}
void add(int idx, int k)
{
for (int i = idx; i <= n; i += lowbit(i))
tr[i] += k;
}
void modify(int l, int r, int k)
{
add(l, k);
add(r + 1, -k);
}
int query(int idx)
{
int ans = 0;
for (int i = idx; i; i -= lowbit(i))
ans += tr[i];
return ans;
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int T;
cin >> T;
while(T--)
{
cin >> n;
fill(tr, tr + n + 2, 0);
ll sum = 0;
for (int i = 1; i <= n; i++)
{
cin >> c[i];
sum += c[i];
modify(i, i, c[i]);
}
int k = sum / n;
for (int i = n; i >= 1; i--)
{
int t = query(i);
int sub = 0;
if (t == i)
{
ans[i] = 1;
sub++;
}
else
ans[i] = 0;
int r = i, l = r - k + 1;
modify(l, r, -1);
k -= sub;
}
for (int i = 1; i <= n; i++)
cout << ans[i] << " ";
cout << endl;
}
return 0;
}