1 条题解

  • 0
    @ 2026-4-7 20:36:00

    考虑扫描序列时动态维护函数 ff,注意到 f(x)≤f(x+1)f(x) \le f(x + 1),容易用线段树维护。

    #include <bits/stdc++.h>
    using namespace std;
    const int D = (1 << 17) - 1;
    const int N = 2.7e5 + 12;
    int a[N], amax[N], b[N];
    void reset(int n, int ll, int rr, int b)
    {
    	a[b] = 0;
    	amax[b] = 0;
    	if (n < ll) return;
    	if (ll == rr) return;
    	int mid = (ll + rr) >> 1;
    	reset(n, ll, mid, b + b);
    	reset(n, mid + 1, rr, b + b + 1);
    }
    void add(int l, int r, int ll, int rr, int b)
    {
    	if (r < 0) return;
    	if (l == ll && r == rr)
    	{
    		a[b]++;
    		amax[b]++;
    		return;
    	}
    	if (a[b])
    	{
    		a[b + b] += a[b];
    		amax[b + b] += a[b];
    		a[b + b + 1] += a[b];
    		amax[b + b + 1] += a[b];
    		a[b] = 0;
    	}
    	int mid = (ll + rr) >> 1;
    	int cl = min(r, mid);
    	int cr = max(l, mid + 1);
    	if (l <= mid) add(l, cl, ll, mid, b + b);
    	if (r > mid) add(cr, r, mid + 1, rr, b + b + 1);
    	amax[b] = max(amax[b + b], amax[b + b + 1]);
    }
    int get(int l, int r, int ll, int rr, int b)
    {
    	if (l == ll && r == rr) return amax[b];
    	if (a[b])
    	{
    		a[b + b] += a[b];
    		amax[b + b] += a[b];
    		a[b + b + 1] += a[b];
    		amax[b + b + 1] += a[b];
    		a[b] = 0;
    	}
    	int mid = (ll + rr) >> 1;
    	int ans = 0;
    	int cl = min(r, mid);
    	int cr = max(l, mid + 1);
    	if (l <= mid) ans = max(ans, get(l, cl, ll, mid, b + b));
    	if (r > mid) ans = max(ans, get(cr, r, mid + 1, rr, b + b + 1));
    	return ans;
    }
    int find(int x, int ll, int rr, int b)
    {
    	if (amax[b] <= x) return rr;
    	if (ll == rr) return -1;
    	if (a[b])
    	{
    		a[b + b] += a[b];
    		amax[b + b] += a[b];
    		a[b + b + 1] += a[b];
    		amax[b + b + 1] += a[b];
    		a[b] = 0;
    	}
    	int mid = (ll + rr) >> 1;
    	int ans = find(x, ll, mid, b + b);
    	if (ans != mid) return ans;
    	return max(mid, find(x, mid + 1, rr, b + b + 1));
    }
    int main()
    {
    	int n;
    	while (cin >> n)
    	{
    		int m = 0;
    		for (int i = 1; i <= n; i++)
    		{
    			cin >> b[i];
    			m = max(m, b[i]);
    		}
    		for (int i = 1; i <= m; i++)
    			add(i, D, 0, D, 1);
    		for (int i = 1; i <= n; i++)
    			if (b[i]) add(0, find(b[i] - 1, 0, D, 1), 0, D, 1);
    		for (int i = 0; i <= m - 1; i++)
    			cout << get(i, i, 0, D, 1) << ' ';
    		cout << get(m, m, 0, D, 1) << endl;
    		reset(m, 0, D, 1);
    	}
    	return 0;
    }
    
    • 1

    [2026 February TFOJ Normal Round] Charity Auctions

    信息

    ID
    252
    时间
    1000ms
    内存
    512MiB
    难度
    7
    标签
    递交数
    2
    已通过
    2
    上传者