1. 程式人生 > >求LIS(O(nlogn))及fill、lower_bound、upper_bound函式

求LIS(O(nlogn))及fill、lower_bound、upper_bound函式

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;
}