BZOJ 2457 [BeiJing2011]双端队列

【题解】

  题目中说将队列进行排序就可以获得一个非降的序列,那么各个队列中的元素有序、同时不同的队列之间也是有序的。

  我们把原序列排序,每个双端队列必定对应一段连续的子序列,且这段子序列里面元素在原序列的位置应该是先递减后递增的。

  那么我们用贪心的策略扫一遍,可以加入当前队列的就加入、更新信息,不行就新开一个队列。

  有个需要特殊考虑的问题是相同的数。如果有多个相同的数,我们可以随意决定他们的顺序,所以我们只需记录它们中最小的位置和最大的位置。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define LL long long
 5 #define rg register
 6 #define N 200010
 7 using namespace std;
 8 int n,m,ans=1;
 9 struct rec{
10     int v,pos;
11 }a[N];
12 struct rec2{
13     int high,low;
14 }b[N];
15 inline int read(){
16     int k=0,f=1; char c=getchar();
17     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
18     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
19     return k*f;
20 }
21 inline bool cmp(rec a,rec b){return a.v<b.v;}
22 int main(){
23     n=read();
24     for(rg int i=1;i<=n;i++) a[i]=(rec){read(),i};
25     sort(a+1,a+1+n,cmp);
26 //    for(rg int i=1;i<=n;i++) printf("[%d %d]\n",a[i].v,a[i].pos);
27     b[m=1]=(rec2){a[1].pos,a[1].pos};
28     for(rg int i=2;i<=n;i++){
29         if(a[i].v!=a[i-1].v) b[++m].low=2e9;
30         b[m].high=max(b[m].high,a[i].pos);
31         b[m].low=min(b[m].low,a[i].pos);
32     }
33 //    printf("%d\n",m);
34 //    for(rg int i=1;i<=m;i++) printf("%d %d\n",b[i].low,b[i].high);
35     int last=2e9; bool type=0;
36     for(rg int i=1;i<=m;i++){
37         if(type){
38             if(b[i].low>=last) last=b[i].high;
39             else ans++,last=b[i].low,type=0;
40         }
41         else{
42             if(b[i].high<=last) last=b[i].low;
43             else last=b[i].high,type=1;
44         }
45 //        printf("()%d %d %d\n",ans,type,last);
46     }
47     printf("%d\n",ans);
48     return 0;
49 }

 

posted @ 2018-11-07 14:08  Driver_Lao  阅读(212)  评论(0编辑  收藏  举报