经典单调栈的模型,基于此制定策略模拟即可。
根据题意,堆的盘子交给艾希来洗的顺序是从左到右,从上到下,故每堆盘子中编号具有单调性,并不同堆间也具有单调性,这样才能做到最终编号从下到上从小到大堆放。
那么如何实现这两个单调性呢?对于新加入的编号为x的盘子,我们可以大致分为三种情况:1.放在第一堆,并把顶上所有编号小于x的盘子洗掉,然后在把x放入第一堆;2.在某一堆的顶部插入x;3.如果所有编号都小于x,给x新建一个堆。当我们发现,第一种情况新洗掉盘子的编号小于已经洗好的盘子堆顶上的最大编号,此时无法再将其往洗好的盘子堆上继续堆放,结束。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 100010;
vector<int> stk[N];int cnt = 1;
int find(int x)
{
int l = 1, r = cnt;
while (l < r)
{
int mid = l + r >> 1;
if (stk[mid][0] >= x) r = mid;
else l = mid + 1;
}
if (stk[l][0] < x) return ++ cnt;
return l;
}
int main()
{
int n, x, res = 1, num = 0;//num表示洗完的盘子最上面的最大编号
cin >> n >> x;
stk[1].push_back(x);
for (int i = 2; i <= n; i ++ )
{
cin >> x;
if (x < num) break;
int pos = find(x);
if (stk[pos].empty() || stk[pos].back() > x) stk[pos].push_back(x);
else
{
while (stk[pos].back() < x)
{
num = stk[pos].back();
stk[pos].pop_back();
}
}
res ++ ;
}
cout << res << endl;
return 0;
}