导弹拦截——线性dp、dilworth定理、最长上升子序列
P1020 [NOIP1999 普及组] 导弹拦截 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这道题和那个木棍加工的题让我懂了最长上升子序列的玩法。
这道题问了两个问题。
问题1:这套系统最多能拦截多少导弹
做法: 既然系统只能拦截不上升的序列。那么我们就求一下最长不上升子序列的长度。
做法和最长上升子序列的做法一样,但是在二分的时候注意要使用upper_bound,理由是:我们求的是小于等于的数,那么等于a[i]的数就不用被挤出来啦,所以用upper。并且,因为求的是不上升子序列,应该是降序,但是upper与lower都只认识升序,所以我们要在使用他俩的时候upper_bound(f+1,f+1+cnt,a[i],greater() )-f。注意要加上greater(),或者用cmp表示递增也可。
问题2:如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。
做法:根据dilworth定理,问题由最少分割为多少个不上升子序列转化为求该序列最长上升子序列的长度。

1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+100; 4 int f[N],a[N],ff[N],ans1,ans2; 5 6 7 int main() 8 { 9 int num,cnt=0; 10 while(~scanf("%d",&num))a[++cnt]=num; 11 //cnt--; 12 13 f[1]=a[1],ff[1]=a[1],ans1=ans2=1; 14 for(int i=2;i<=cnt;i++) //最长不上升子序列 15 { 16 if(a[i]<=f[ans1])f[++ans1]=a[i]; 17 else 18 { 19 int k=upper_bound(f+1,f+1+ans1,a[i],greater<int>() )-f; 20 f[k]=a[i]; 21 } 22 } 23 printf("%d\n",ans1); 24 25 for(int i=2;i<=cnt;i++) //最长上升子序列 26 { 27 if(a[i]>ff[ans2])ff[++ans2]=a[i]; 28 else 29 { 30 int k=lower_bound(ff+1,ff+1+ans2,a[i])-ff; 31 ff[k]=a[i]; 32 } 33 } 34 printf("%d\n",ans2); 35 36 37 return 0; 38 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!