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;
}

posted @ 2022-05-12 21:08  hzy0227  阅读(23)  评论(0编辑  收藏  举报