2457: [BeiJing2011]双端队列

2457: [BeiJing2011]双端队列

链接

  很奇妙的转化。

  题目要求最后的所有序列也是有序的,所以可以求出最后的序列(即排序后的序列),然后分成许多份,要求每一份都是一个双端序列,求最少分成多少份。

  一个结论或者规律:每一个双端队列的数对应原序列的下标都是先下降后增加的(考虑双端序列的构造过程,加入一个数,坐标为a,往后枚举的数要么在序列前,要么加入到后,而且往后的数的下标都比a大,所以是先下降后递增的)

  那么就是求排序后的序列,的坐标最少多少先下降后上升的序列。

  相同的数可以放到同一个双端序列中,一起考虑。

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 
 5 inline int read() {
 6     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
 7     for (;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
 8 }
 9 
10 const int N = 200010;
11 
12 struct Node{
13     int x,pos;
14     bool operator < (const Node &A) const {
15         if (x == A.x) return pos < A.pos;
16         return x < A.x;
17     }
18 }a[N];
19 
20 int Mx[N],Mn[N];
21 
22 int main() {
23     int n = read();
24     for (int i=1; i<=n; ++i) {
25         a[i].x = read(),a[i].pos = i;
26     }
27     sort(a+1,a+n+1);
28     int tot = 0;
29     for (int i=1; i<=n; ++i) {
30         if (a[i].x != a[i-1].x || i==1) {
31             Mx[tot] = a[i-1].pos;
32             Mn[++tot] = a[i].pos;
33         }
34     }
35     Mx[tot] = a[n].pos;
36     
37     int flag = 1,H = 0x7fffffff,ans = 0;
38     for (int i=1; i<=tot; ++i) {
39         if (!flag) { // 求下降的过程 
40             if (H > Mx[i]) H = Mn[i]; // 下降 
41             else H = Mx[i],flag = 1; // 转折,变为上升 
42         }
43         else { // 求上升的过程 
44             if (H < Mn[i]) H = Mx[i]; // 上升 
45             else H = Mn[i],flag = 0,ans++; // 转折,变为下降,表示新增加一个双端序列,ans++ 
46         }
47     }
48     cout << ans;
49     return 0;
50 }

 

posted @ 2018-07-05 20:38  MJT12044  阅读(278)  评论(0编辑  收藏  举报