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

浙公网安备 33010602011771号