已知两个长度为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。
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; }