牛客 双端队列

https://ac.nowcoder.com/acm/contest/1006/C

题面

有N个整数需要排序,能用的工具是若干个双端队列。
需要依次处理这N个数,可以:

  • 新建一个双端队列,并将当前数作为这个队列中的唯一的数;
  • 将当前数放入已有的队列的头之前或者尾之后。
    要求:对所有的数处理完成之后,将这些队列排序后就可以得到一个非降的序列。

分析

考虑排完后的序列,它是由若干双端队列组成。
发现:对于每个双端队列,每个元素换成它在原有序列中的位置,一定是一个先单调减后单调增的序列。
但要讨论相同的情况
发现:存在一种最优解,满足相同的元素在同一个双端队列中

#include<bits/stdc++.h>
const int INF=1e9;
using namespace std;

const int N=2e5+5;
int n,m,b[N],c[N],mn[N],mx[N];
struct A{int x,id;}a[N];
bool cmp(A i,A j) {return i.x<j.x; }

int main() {
	scanf("%d",&n);
	for(int i=1;i<=n;i++) {
		scanf("%d",&a[i].x); a[i].id=i;
	}
	sort(a+1,a+n+1,cmp); 
	for(int i=1;i<=n;i++) {
		if(i==1||a[i].x!=a[i-1].x) b[++m]=a[i].id,c[m]=1,mn[m]=mx[m]=b[m];
			else c[m]++,mn[m]=min(mn[m],a[i].id),mx[m]=max(mx[m],a[i].id);
	}
	int l=1,lst=INF,ans=0; 	
	while(l<=m) {
		ans++; lst=INF;
		while(l<=m&&(c[l]==1&&b[l]<lst||c[l]>1&&mx[l]<lst)) lst=(c[l]==1?b[l]:mn[l]),l++;
		if(lst==INF) lst=-INF;
		if(c[l]>1&&mn[l]<lst) lst=mn[l]-1;
		while(l<=m&&(c[l]==1&&b[l]>lst||c[l]>1&&mn[l]>lst)) lst=(c[l]==1?b[l]:mx[l]),l++;
	}
	printf("%d\n",ans);
	return 0;
}
posted @ 2020-11-27 10:44  wwwsfff  阅读(100)  评论(0)    收藏  举报