题意:
有n个按顺序摆放好的盘子,每个盘子都有一个序号,现在有无数个空的栈,按顺序操作盘子,每次你有两个操作
1.把当前的盘子放到某个栈的最顶上或者在栈的最右边新建一个栈,把盘子放进去。
2.从非空栈的最左边的栈的最顶上拿一个盘子。
要求:按盘子序号从小到大拿出。
但是有可能并不能将所有盘子按序号拿出,所以问你最多能将序列中的前几个盘子按序号拿出。
题解:
一看就是二分。在二分答案的时候我们按顺序处理每个盘子,遇到一个盘子的时候upper_bound所有栈的最低端元素,以确定它是在哪个栈里面的。所以我们需要用一个数组维护栈底元素。当找到的栈的栈顶小于这个数的时候,那么必须要pop,然后记录一个已经pop的元素的最大值,这样之后如果有小的值过来的时候,它无处安放。这样就是不行的。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N],bot[N];
stack<int>s[N];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
s[1].push(a[1]);
int l=1,r=1,mx=0;
bot[1]=a[1];
for(int i=1;i<=n;i++){
if(a[i]<mx)
return 0*printf("%d\n",i-1);
int p=upper_bound(bot+l,bot+r+1,a[i])-bot;
if(p==r+1)
s[++r].push(a[i]),bot[r]=a[i];
while(s[p].top()<a[i])
mx=s[p].top(),s[p].pop();
s[p].push(a[i]);
}
printf("%d\n",n);
}