2457: [BeiJing2011]双端队列
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 209 Solved: 95
[Submit][Status][Discuss]
Description
Sherry现在碰到了一个棘手的问题,有N个整数需要排序。
Sherry手头能用的工具就是若干个双端队列。
她需要依次处理这N个数,对于每个数,Sherry能做以下两件事:
1.新建一个双端队列,并将当前数作为这个队列中的唯一的数;
2.将当前数放入已有的队列的头之前或者尾之后。
对所有的数处理完成之后,Sherry将这些队列排序后就可以得到一个非降的序列。
Input
第一行包含一个整数N,表示整数的个数。接下来的N行每行包含一个整数Di,其中Di表示所需处理的整数。
Output
其中只包含一行,为Sherry最少需要的双端队列数。
Sample Input
6
3
6
0
9
6
3
3
6
0
9
6
3
Sample Output
2
HINT
100%的数据中N≤200000。
先简化一拨题意。
大约是说有这样多个双端队列用。
然后队列有序。
队列内元素有序。
问最多几个能满足最后的序列有序。
我们先排序一遍,按两个关键字,第二个关键字是数组位置从大到小。
发现样例的位置序列如此:3 1 6 2 5 4
仔细想一想
队列里面的元素必须连续
大约一个队列能处理一段的要求是pos 从大到小 然后到最低从小到最大。
一个这样的折点大约就用一个队列
当然还有特殊情况——相等的数。
相等的数显然可以放在一个队列中....因为我可以控制其递增或递减,于是只需要记录最大值和最小值,然后当成一个整体就好。
贪心+模拟的时候:
![【贪心】Bzoj 2457:[BeiJing2011]双端队列 【贪心】Bzoj 2457:[BeiJing2011]双端队列](https://image.miaokee.com:8440/aHR0cHM6Ly9pbWFnZXMyMDE1LmNuYmxvZ3MuY29tL2Jsb2cvNzczNjg4LzIwMTUxMC83NzM2ODgtMjAxNTEwMTAwOTE2MDkxMTItNzM4MTkxOTUwLnBuZw%3D%3D.png?w=700&webp=1)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath> #define maxn 200100 using namespace std; struct node{
int x,pos;
}a[maxn]; int mx[maxn],mi[maxn]; inline int in()
{
int x=,f=;char ch=getchar();
while((ch<''||ch>'')&&ch!='-')ch=getchar();
if(ch=='-')f=-,ch=getchar();
while(ch<=''&&ch>='')x=x*+ch-'',ch=getchar();
return x*f;
} bool cmp(const node A,const node B){return A.x<B.x||(A.x==B.x&&A.pos<B.pos);} int main()
{
int n,cnt=,ans=,h=,b=;
n=in();
for(int i=;i<=n;i++)a[i].x=in(),a[i].pos=i;
sort(+a,+a+n,cmp);
for(int i=;i<=n;i++)
if(i==||a[i].x!=a[i-].x)
{
mx[cnt]=a[i-].pos;
mi[++cnt]=a[i].pos;
}
mx[cnt]=a[n].pos;
for(int i=;i<=cnt;i++)
{
if(!b)
{
if(h>mx[i])h=mi[i];
else h=mx[i],b=;
}
else{
if(h<mi[i])h=mx[i];
else h=mi[i],b=,ans++;
}
}
printf("%d",ans);
return ;
}