题目
Sherry 现在碰到了一个棘手的问题, 有N个整数需要排序
Sherry 手头能用的工具就是若干个双端队列
她需要依次处理这 N 个数, 对于每个数, Sherry 能做以下两件事:
1.新建一个双端队列, 并将当前数作为这个队列中的唯一的数;
2.将当前数放入已有的队列的头之前或者尾之后
对所有的数处理完成之后, Sherry 将这些队列排序后就可以得到一个非降的序列
输入格式
第一行包含一个整数 N, 表示整数的个数接下来的 N 行每行包含一个整数 Di, 其中 Di 表示所需处理的整数
输出格式
其中只包含一行, 为 Sherry 最少需要的双端队列数
输入样例
- 6
- 3
- 6
- 0
- 9
- 6
- 3
输出样例
2
提示
100% 的数据中 N200000
题解
由于最后排序的连续性, 双端队列中元素的添加在最终排序中一定是连续的
所以我们在一个双端队列中加入一个元素后, 那么其仅可以向次小或次大方向扩展
我们将位置按数值大小排序, 显然每个低谷的地方是一段中最先出现的位置, 这个位置先加入双端队列, 然后就可以顺序向两端扩展
但是大小相同的元素可以互换位置
问题就转化为了: 可以移动一些区间内的元素位置, 求波谷最小的序列
贪心取每个区间最大最小讨论一下
- #include<iostream>
- #include<cstdio>
- #include<cmath>
- #include<cstring>
- #include<algorithm>
- #define LL long long int
- #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
- #define REP(i,n) for (int i = 1; i <= (n); i++)
- #define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<< ; puts("");
- using namespace std;
- const int maxn = 200005,maxm = 100005,INF = 0x7fffffff;
- inline int read(){
- int out = 0,flag = 1; char c = getchar();
- while (c < 48 || c > 57){if (c == -) flag = -1; c = getchar();}
- while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
- return out * flag;
- }
- int A[maxn],id[maxn],n;
- inline bool cmp(const LL& a,const LL& b){return A[a] < A[b];}
- int main(){
- n = read();
- if (!n) {puts("0"); return 0;}
- for (int i = 1; i <= n; i++) A[i] = read(),id[i] = i;
- sort(id + 1,id + 1 + n,cmp);
- int way = 0,ans = 1,last = INF;
- for (int i = 1; i <= n; i++){
- int r = i,mx = id[i],mn = id[i];
- while (r < n && A[id[r + 1]] == A[id[r]]){
- r++;
- mx = max(mx,id[r]);
- mn = min(mn,id[r]);
- }
- i = r;
- if (!way){
- if (mx < last) last = mn;
- else last = mx,way = 1;
- }else {
- if (mn > last) last = mx;
- else last = mn,way = 0,ans++;
- }
- }
- printf("%d\n",ans);
- return 0;
- }
来源: http://www.bubuko.com/infodetail-2523983.html