已知两个长度为N的数组A和B。下标从0标号至N-1。
如今定义一种D序列 (如果长度为L)。这样的序列满足下列条件:
1. 0 <= D[i] <= N-1
2. A[D[i]] < A[D[i+1]] (0 <= i < L-1)
3. B[D[i]] > B[D[i+1]] (0 <= i < L-1)
求满足条件的D序列的最大长度。
(事实上这样的序列叫做D序列的原因是:这道题是D题)
多组数据,每组数据第一行是一个整数N。
(1 <= N <= 100000)
第二行中有N个正整数A[0]~A[N-1]。
第三行中有N个正整数B[0]~B[N-1]。
保证全部输入整数在int范围内。
对每组数据。输出一个整数。表示D序列的最大长度L。
在这里a[ i ] > s[ j ]&&a[i]<=s[ j + 1 ]就应该把a[ i ]放在s[ j+1 ]的位置。
所以关键就是找出 j 就知道把a[ i ]放在哪了。
上面的两种方法就是用来寻找 j的 。(在这里lower_bound直接返回 j + 1 )
| 0 | 1 | 2 | 3 | 4 | 
| 1 | 3 | |||
| 2 | 2 | |||
| 3 | 2 | 4 | ||
| 4 | 2 | 4 | 6 | |
| 5 | 2 | 4 | 5 | |
| 6 | 2 | 4 | 5 | 7 | 
| 7 | 2 | 3 | 5 | 7 | 
#include <bits/stdc++.h>
using namespace std;
int a[100005],b[100005];
int s[100005];
vector<pair<int,int> > T;//能够用vector存,也能够直接用数组 pair<int ,int> T[100005];
int main()
{
    int n;
    while(~scanf("%d",&n)){
        T.clear();//假设不初始或要出错用数组就不须要了
        for(int i = 0;i<n;i++)scanf("%d",&a[i]);
        for(int i = 0;i<n;i++)scanf("%d",&b[i]);
        //假设用数组应该为T[i] = {a[i],b[i]};
        for(int i = 0;i<n;i++)T.push_back(make_pair(a[i],b[i]));
        //sort(T,T+n);
        std::sort(T.begin(),T.end());//排序
        for(int i= 0;i<n;i++)a[i] = T[i].second;//把排序后的数组b取出来放到a中
        reverse(a,a+n);//导致
        int len = 1; s[1] = a[0];//<span style="font-family: Arial, Helvetica, sans-serif;">第一个元素首先放入 s[1]</span>
        for(int i = 1;i<n;i++){//dp的思想,逐个将a中元素增加s.
            int t = a[i];
            if(t>s[len])s[++len] = a[i];
            else{
                int p = lower_bound(s+1,s+len+1,t)-s;
                s[p] = t;
            }
        }
        printf("%d\n",len);
    }
    return 0;
}
方法(2)代码::#include <bits/stdc++.h>
using namespace std;
int a[100005],b[100005];
int s[100005];
vector<pair<int,int> > T;
 
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        T.clear();
        for(int i = 0;i<n;i++)scanf("%d",&a[i]);
        for(int i = 0;i<n;i++)scanf("%d",&b[i]);
        for(int i = 0;i<n;i++)T.push_back(make_pair(a[i],b[i]));
        std::sort(T.begin(),T.end());
        for(int i= 0;i<n;i++)a[i] = T[i].second;
        reverse(a,a+n);
        int len = 1;s[1] = a[0];
        for(int i = 1;i<n;i++){
            int t = a[i];
            if(t>s[len]) s[++len] = a[i];
            else{
                int l = 1,r = len,mid;
                int ans = 0;
                while(l<=r)//这里的二分法採用了左闭右闭的思路
                {
                    mid = (r+l)/2;
                    if(s[mid]<t){
                        l = mid+1;
                        ans=max(ans, mid);//ans即为思路中的j,j必定为s数组中小于t的最大的数
                    } 
                    else r = mid-1;
                }
                s[ans+1] = t;
            }
        }
        printf("%d\n",len);
    }
    return 0;
}原文:http://www.cnblogs.com/yfceshi/p/6970710.html