#双端队列 ——Acwing 134. 双端队列

题目

达达现在碰到了一个棘手的问题,有N个整数需要排序。

达达手头能用的工具就是若干个双端队列。

她从1到N需要依次处理这N个数,对于每个数,达达能做以下两件事:

1.新建一个双端队列,并将当前数作为这个队列中的唯一的数;

2.将当前数放入已有的队列的头之前或者尾之后。

对所有的数处理完成之后,达达将这些队列按一定的顺序连接起来后就可以得到一个非降的序列。

请你求出最少需要多少个双端序列。

输入格式
第一行输入整数N,代表整数的个数。

接下来N行,每行包括一个整数Di,代表所需处理的整数。

输出格式
输出一个整数,代表最少需要的双端队列数。

数据范围
1≤N≤200000

.

输入样例:
6
3
6
0
9
6
3
输出样例:
2

答案

#include<bits/stdc++.h>
using namespace std;
deque<int>q[1010];
const int N=200006,INF=0x3f3f3f3f;
pair<int,int>a[N];
int n;
vector<int>p[N];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].first;//保存数值; 
		a[i].second=i;//保存输入时的顺序; 
	}
	sort(a+1,a+n+1);//按数值给序号排序; 
	int t=0;//准备工作
	for(int i=1;i<=n;i++){
		p[++t].push_back(a[i].second);
		while(a[i].first==a[i+1].first)
		p[t].push_back(a[++i].second);
	}
	for(int i=1;i<=t;i++)sort(p[i].begin(),p[i].end());
	bool flag=0;/*判断上升或下降的趋势,一开始判它为下降趋势。
	(因为下一个趋势一定是上升的,但现在是第一个数值队列,没有趋势。
	要为上升趋势准备)
	*/
	int num=INF,ans=1;/*ans设为1,此题意在找拐点,找到拐点后要加1才算是队列数量,
	因此开始为1;*/
	for(int i=1;i<=t;i++){
		int s=p[i].size();
		if(flag){//上升趋势
			if(num<p[i][0]) num=p[i][s-1];/*这里的上升趋势时,
			num这个位置应现在的值的队头的左方才能保证整个队列的上升趋势*/
			else{//不然就肯定有一个趋势的变化
				 ans++;/*因为每换两次趋势才会有一个拐点
				 (一次趋势的变化可以看做一个队列,再多一个就要开多一个队列)
				 所以我们选择在上升时多开一个队列*/
				 flag=0;//转下降趋势
				 num=p[i][0];
			}
		}
		else{//下降趋势
			if(num>p[i][s-1]) num=p[i][0];/*下降趋势时,num应在此数值队尾的右边
			否则有转趋势*/
			else{
				flag=1;//转上升趋势;
				num=p[i][s-1];
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}

这道题重点在找“拐点”,与队列没有半毛钱关系,超坑。

原文地址:https://www.cnblogs.com/yuanyulin/p/14026795.html