1. 程式人生 > 實用技巧 >P1020 導彈攔截(樹狀陣列+DP)

P1020 導彈攔截(樹狀陣列+DP)

題目描述

某國為了防禦敵國的導彈襲擊,發展出一種導彈攔截系統。但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能高於前一發的高度。某天,雷達捕捉到敵國的導彈來襲。由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的導彈。

輸入導彈依次飛來的高度(雷達給出的高度資料是\le 5000050000的正整數),計算這套系統最多能攔截多少導彈,如果要攔截所有導彈最少要配備多少套這種導彈攔截系統。

輸入格式

11行,若干個整數(個數\le 100000100000)

輸出格式

22行,每行一個整數,第一個數字表示這套系統最多能攔截多少導彈,第二個數字表示如果要攔截所有導彈最少要配備多少套這種導彈攔截系統。

題解:

求一個最長嚴格單調遞增子序列和最長不嚴格單調遞減子序列。

讀入很毒瘤

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+100;
int a[maxn];
int r[maxn];
int l[maxn];
int c[maxn];
int lowbit(int x) {
    return x&-x;
}
void update (int x,int v) {
    for (int i=x;i<maxn;i+=lowbit(i)) c[i]=max(c[i],v);
}
int
getMax (int x) { int ans=0; for (int i=x;i;i-=lowbit(i)) ans=max(ans,c[i]); return ans; } int main () { int n; while (cin>>a[++n]); n--; int pre=0,u=1; int ans=0; for (int i=n;i>=1;i--) { r[i]=getMax(a[i])+1; update(a[i],r[i]); } int
Max=0; for (int i=1;i<=n;i++) Max=max(Max,r[i]); memset(c,0,sizeof(c)); for (int i=1;i<=n;i++) { l[i]=getMax(a[i]-1)+1; update(a[i],l[i]); } for (int i=1;i<=n;i++) ans=max(ans,l[i]); printf("%d\n%d\n",Max,ans); }