导弹拦截 dp

nlognn*logn写法,lis[i]ialis[i]的意义为:所有最长上升子序列长度为i的位置上的最小a数组元素值。然后转移一下即可。

#include<bits/stdc++.h>

#define LL long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back

using namespace std;

LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
LL lcm(LL a,LL b){return a/gcd(a,b)*b;}
LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
int n;
const int N=1e5+43;
int dp[N],lis[N],a[N];
int b[N];
int main(){
	ios::sync_with_stdio(false);
	int q;
	while(cin>>q)a[++n]=q;
	// cout<<n<<endl;
	for(int i=1;i<=n;i++)dp[i]=1,lis[i]=2e9,b[n-i+1]=a[i];
	for(int i=1;i<=n;i++){
		int pos=upper_bound(lis+1,lis+1+n,a[i])-lis;
		while(lis[pos]>=a[i])pos--;
		dp[i]=pos+1;
		lis[dp[i]]=min(lis[dp[i]],a[i]);
	}
	int ans1=*max_element(dp+1,dp+1+n);
	for(int i=1;i<=n;i++)a[i]=b[i];
	for(int i=1;i<=n;i++)lis[i]=2e9;
	memset(dp,1,sizeof dp);
	for(int i=1;i<=n;i++){
		int pos=upper_bound(lis+1,lis+1+n,a[i])-lis;
		dp[i]=pos;
		lis[dp[i]]=min(lis[dp[i]],a[i]);
	}
	cout<<*max_element(dp+1,dp+1+n)<<endl;	
	cout<<ans1<<endl;
	return 0;
}
// 12
// 6```

原文地址:https://www.cnblogs.com/pubgoso/p/10759718.html