牛客 双端队列
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;
}

浙公网安备 33010602011771号