题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1257
题目中说明炮弹只能像更高的位置发射,对于发射高度X,<=X的高度这个炮弹是可以射到的,所以我们可以先考虑第一个高度,找出最长下降子序列,将其从原序列中删去,接着找下一个最长下降子序列,再将其从原序列中删去,这样迭代下去我们会得到k个最长下降子序列的集合,k就是所需要的最小导弹的数量。
其实并不需要这么麻烦地求解这个问题,有这样一个结论,后一个取出的最长下降子序列一定存在一个元素a至少大于前一个最长下降子序列中的一个元素,否则后一个a可以合并到第一个子序列中。我们可以从这k个最长下降子序列中取出k个元素构成上升子序列,这个上升子序列一定是原序列的最长上升子序列。如果这个递增子序列不是最长的,就可以从某一个最长下降子序列中找出两个值c,d在递增子序列中,此时有c>d,与递增子序列的定义矛盾,所以k=LIS()。
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned int ui; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define pf printf 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 #define prime1 1e9+7 9 #define prime2 1e9+9 10 #define pi 3.14159265 11 #define lson l,mid,rt<<1 12 #define rson mid+1,r,rt<<1|1 13 #define scand(x) scanf("%llf",&x) 14 #define f(i,a,b) for(int i=a;i<=b;i++) 15 #define scan(a) scanf("%d",&a) 16 #define mp(a,b) make_pair((a),(b)) 17 #define P pair<int,int> 18 #define dbg(args) cout<<#args<<":"<<args<<endl; 19 #define inf 0x7ffffff 20 inline int read(){ 21 int ans=0,w=1; 22 char ch=getchar(); 23 while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();} 24 while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar(); 25 return ans*w; 26 } 27 int n,m,t; 28 const int maxn=1e6+10; 29 int a[maxn],dp[maxn]; 30 int LIS() 31 { 32 dp[1]=a[1]; 33 int len=1; 34 f(i,2,n) 35 { 36 if(a[i]>=dp[len])dp[++len]=a[i]; 37 else 38 { 39 int l=0,r=len; 40 while(l<r) 41 { 42 int mid=l+r>>1; 43 if(dp[mid]>a[i])r=mid; 44 else l=mid+1; 45 } 46 dp[l]=a[i]; 47 } 48 } 49 return len; 50 } 51 int main() 52 { 53 //freopen("input.txt","r",stdin); 54 //freopen("output.txt","w",stdout); 55 std::ios::sync_with_stdio(false); 56 while(~scanf("%d",&n)) 57 { 58 f(i,1,n)a[i]=read(); 59 pf("%d ",LIS()); 60 } 61 }