【luogu1020】 导弹拦截 [动态规划LIS]

P1020 导弹拦截

就是找最长不上升子序列长度和最少由几个最长不下降子序列覆盖

最长不上升子序列就把它翻转过来求其翻转之后数列的最长不下降子序列 所以不能用lower_bound得手写QAQ 然后我又被二分卡了好久 我是个弟弟

最少由几个最长不下降子序列覆盖 就等于求它原来数组的最长上升子序列的长度 (你想,如果它后面的高度大于了它肯定要再发一个啊)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define rg register
 4 const int N=100000+5,inf=0x3f3f3f3f;
 5 int n=0,a[N],b[N];
 6 int gb[N],ga[N],la=0,lb=0;
 7 
 8 template<class t>void rd(t &x)
 9 {
10     x=0;int w=0;char ch=0;
11     while(!isdigit(ch)) w|=ch=='-',ch=getchar();
12     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
13     x=w?-x:x;
14 }
15 
16 int find(int x)
17 {
18     int l=1,r=lb,mid,ans;
19     while(l<=r)
20     {
21         mid=l+((r-l)>>1);
22         if(x>=gb[mid]) l=mid+1;
23         else r=mid-1;
24     }
25     return l;
26 }
27 
28 int main()
29 {
30 //    freopen("in.txt","r",stdin);
31     while(scanf("%d",&a[++n])==1) b[n]=a[n];--n;
32     reverse(b+1,b+1+n);
33     memset(ga,inf,sizeof(ga));
34     memset(gb,inf,sizeof(gb));
35     for( int i=1;i<=n;++i)
36     {
37         int k=find(b[i]);//lower_bound(gb+1,gb+1+n,b[i])-gb
38         gb[k]=b[i],lb=max(lb,k);
39         k=lower_bound(ga+1,ga+1+n,a[i])-ga;
40         ga[k]=a[i],la=max(la,k);
41     }
42     printf("%d
%d",lb,la);
43     return 0; 
44 } 
原文地址:https://www.cnblogs.com/lxyyyy/p/10804655.html