Description
Sherry现在碰到了一个棘手的问题,有N个整数需要排序。 Sherry手头能用的工具就是若干个双端队列。 她需要依次处理这N个数,对于每个数,Sherry能做以下两件事: 1.新建一个双端队列,并将当前数作为这个队列中的唯一的数; 2.将当前数放入已有的队列的头之前或者尾之后。 对所有的数处理完成之后,Sherry将这些队列排序后就可以得到一个非降的序列。
Input
第一行包含一个整数N,表示整数的个数。接下来的1行包含N个整数Di,其中Di表示所需处理的整数。
Output
其中只包含一行,为Sherry最少需要的双端队列数。
Sample Input
6 3 6 0 9 6 3
Sample Output
2
Hint
N≤200000
分析
若将输入数组a b为a将a排序后的数组 因为将队列排序后能得到单调序列,所以每一个队列为排序后都为排序后数组中连续一段 所以现在问题转化为求b中满足条件的最少划分段数
现在我们再来看怎样的划分是满足条件的 假设其中一个合法的为a[i],a[i+1]…a[j-1],a[j] 不难发现最终队列下标情况为i最小且i两边单调且单调性不同 大概是这样 就这样就行了
标程
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define SIZE 200005
using namespace std
;
struct kkk
{
int v
,num
;
bool operator < (const kkk
&other
) const
{
if(v
!= other
.v
)
return v
< other
.v
;
else
return num
< other
.num
;
}
}a
[SIZE
];
int maxa
[SIZE
],mina
[SIZE
];
int main()
{
freopen("deque.in","r",stdin);
freopen("deque.out","w",stdout);
memset(maxa
,0xaf,sizeof(maxa
));
memset(mina
,0x7f,sizeof(mina
));
int n
;
scanf("%d",&n
);
for(int i
= 0;i
< n
;i
++)
scanf("%d",&a
[i
].v
),a
[i
].num
= i
;
sort(a
,a
+n
);
int nowa
= a
[0].v
,nowk
= 0;
int tot
= 0;
for(int i
= 0;i
< n
;i
++)
{
if(a
[i
].v
== nowa
)
a
[i
].v
= nowk
;
else
{
nowa
= a
[i
].v
;
nowk
++;
a
[i
].v
= nowk
;
}
}
for(int i
= 0;i
< n
;i
++)
{
maxa
[a
[i
].v
] = max(maxa
[a
[i
].v
],a
[i
].num
);
mina
[a
[i
].v
] = min(mina
[a
[i
].v
],a
[i
].num
);
}
if(nowk
== 0)
{
cout
<<1;
return 0;
}
bool flag
= true;
int tot1
= 1,tot2
= 0;
for(int i
= 1;i
<= nowk
;i
++)
{
if(flag
)
{
if(mina
[i
] < maxa
[i
-1])
flag
= false;
}
else
{
if(maxa
[i
] > mina
[i
-1])
{
flag
= true;
tot1
++;
}
}
}
if(!flag
)
tot1
++;
flag
= false;
for(int i
= 1;i
<= nowk
;i
++)
{
if(flag
)
{
if(mina
[i
] < maxa
[i
-1])
flag
= false;
}
else
{
if(maxa
[i
] > mina
[i
-1])
{
flag
= true;
tot2
++;
}
}
}
if(!flag
)
tot2
++;
cout
<<min(tot2
,tot1
);
}