题目:奥运大包围

题目描述

题目描述:
为了迎接奥运,市体育局举行手拉手大包围活动,开始时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     } 

转载于:https://www.cnblogs.com/noip/archive/2012/08/23/2653047.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值