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 }