题目:奥运大包围

题目描述

题目描述:
为了迎接奥运,市体育局举行手拉手大包围活动,开始时N个人手拉手围成一个圈。后来这些人中的一些按顺序向里面出圈形成一个新圈。从而使原圈形成一个从高到低,最低与最高连接的圈。新圈重复相同的操作,直到没有人要出圈为止。问最少要形成多少个这样的圈。

输入格式

输入:第一行N个人,第二行输入N个人的身高(每个身高中用空格隔开)N<=1000

输出格式

输出:最少形成多少个这样的圈。

 

 

定理:下降子序列的个数等于最长不下降子序列的长度。

稍微想一想就明白了。

将圈拆成段枚举就是了。二分优化:最长不下降子序列的O(n*logn)算法

话说和[NOIP1999]拦截导弹 差不多,应该也可以用贪心。

 1 #include<iostream>
 2 //#include<fstream> 
 3 using namespace std;
 4 //ifstream fin("cin.in");
 5 
 6 int n,h[2005],c[2005],len=0,ans=10000;
 7 
 8 int Find(int x){
 9     int l=1,r=len,mid=(len+1)>>1;
10     while(l<=r)
11     {
12       mid=(l+r)>>1;
13       if(c[mid]<=x) l=mid+1;     
14       else if(c[mid]>x) r=mid-1;   
15                 }
16     return l;
17     }
18 
19 int main()
20 {
21     cin>>n;
22     for(int i=1;i<=n;++i) cin>>h[i],h[i+n]=h[i];
23     
24     for(int i=1;i<=n;++i)
25     {
26       len=1;
27       c[1]=h[i];
28       
29       for(int j=i+1;j-i<n;++j)
30       {
31         int k=Find(h[j]);
32         if(k==len+1) len++;
33         c[k]=h[j];
34               }
35       ans=min(ans,len);    
36             }
37     
38     cout<<ans<<endl;
39   //  system("pause");
40     return 0;
41 
42     } 
posted on 2012-08-23 19:59  怡红公子  阅读(282)  评论(0编辑  收藏  举报