1. 程式人生 > 其它 >CF Round #782 D - Reverse Sort Sum

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