求LIS(O(nlogn))及fill、lower_bound、upper_bound函式
阿新 • • 發佈:2019-01-31
lower_bound(a,a+n,k) 二分求ai>=k的ai的最小的指標。
upper_bound(a,a+n,k) 二分求ai>k的ai的最小的指標。
例:可以求長度為n的有序陣列a中的k的個數,即為upper_bound(a,a+n,k)-lower_bound(a,a+n,k)。
fill(a,a+n,x);
將陣列a0~an位置賦值為x。
下面為nlogn時間內求LIS。
#include<iostream> #include<stdio.h> #include<math.h> #include <string> #include<string.h> #include<map> #include<set> #include<algorithm> #include<stdlib.h> using namespace std; #define pi 3.1415926535898 #define eps 1e-8 #define inf 0x3f3f3f3f #define rd(x) scanf("%d",&x) #define rd2(x,y) scanf("%d%d",&x,&y) #define ll long long int #define maxn 100005 int dp[maxn]; int a[maxn]; int n; void solve(){//求最長上升子序列(LIS)(nlogn) fill(dp,dp+n,inf);//fill函式是用來把0~n的位置賦值為某個值 for(int i=0;i<n;i++) { *lower_bound(dp,dp+n,a[i])=a[i]; //如果子序列的長度相同,那麼最末位的元素較小的在之後的會更加有優勢, //所以我們反過來用dp針對長度相同的情況下最小的末尾元素進行求解。 } printf("%d\n",lower_bound(dp,dp+n,inf)-dp); } int main() { rd(n); for(int i=0;i<n;i++) { rd(a[i]); } solve(); return 0; }