P6198 [EER1] 单调栈 解题报告

\(S_i\) 表示在处理完元素 \(p_i\) 后,单调栈的大小。

  • \(S_i > S_{i-1}\) 时:这意味着 \(p_i\) 被压入了栈,并且没有弹出任何元素。这发生在 p_i 大于栈顶元素时。此时,\(S_i = S_{i-1} + 1\)

  • \(S_i < S_{i-1}\) 时:这意味着 \(p_i\) 被压入栈前,弹出了 \(S_{i-1} - S_i\) 个元素。这发生在 \(p_i\) 小于或等于栈顶元素时。此时,\(S_i\) 的值就是弹出元素后栈的大小再加 \(1\)

  • \(S_i = S_{i-1}\) 时:这意味着 \(p_i\) 压入栈前,弹出了一个元素。

可以得出一个结论:\(S_i\) 的值实际上代表了元素 \(p_i\) 在最终单调栈中的深度。

所以可以这么做

用贪心策略(S[i] = S[i-1] + 1)填充 S 序列中的所有 -1。

根据完整的 S 序列,构建一棵表示元素层级覆盖关系的树。

对这棵树进行特殊的后序 DFS 遍历,按访问顺序依次分配 1 到 n 的数值,从而得到字典序最小的排列。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 5;
int n, k, num, a[N], b[N], f[N];
vector<int> ve[N];

void dfs(int x)
{
	if (ve[x].size() <= 0)
	{
		return ;
	}
	
	for (int i = ve[x].size() - 1; i >= 0; i --)
	{
		num ++;
		a[ve[x][i]] = num;
	}
	for (int i = 0; i < ve[x].size(); i ++)
	{
		dfs(ve[x][i]);
	}
}

signed main()
{
	cin >> n;
	for (int i = 1; i <= n; i ++)
	{
		cin >> b[i];
		if (b[i] == -1)
		{
			b[i] = b[i - 1] + 1;	
		}
	}
	for (int i = 1; i <= n; i ++)
	{
		ve[f[b[i] - 1]].push_back(i);
		f[b[i]] = i;
	}
	dfs(0);
	for (int i = 1; i <= n; i ++)
	{
		cout << a[i] << " ";
	}
}
posted @ 2026-06-21 16:47  Luowj  阅读(6)  评论(0)    收藏  举报