1. 程式人生 > >【luogu1020】 導彈攔截 [動態規劃LIS]

【luogu1020】 導彈攔截 [動態規劃LIS]

gist -- sin printf 動態規劃 git can etc stdin

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\n%d",lb,la); 43 return 0; 44 }

【luogu1020】 導彈攔截 [動態規劃LIS]