一开始,我一直是这么写的(导弹拦截的时候这么写也没问题):
#include <iostream>
#include <cstdio>
using namespace std;
int n, l, r, mid, cnt, ans;
int p1[100005], p2[100005], mp[100005], dp[100005]={1145140};
int main(){
scanf("%d", &n);
for(int i=1; i<=n; i++)scanf("%d", &p1[i]), mp[p1[i]]=i;
for(int i=1; i<=n; i++)scanf("%d", &p2[i]), p2[i]=mp[p2[i]];
for(int i=1; i<=n; i++){
l=0, r=n;
while(l<=r){
mid=(l+r)/2;
if(dp[mid]>=p2[i]){
cnt=mid;
l=mid+1;
}
else r=mid-1;
}
ans=max(ans,cnt+1);
dp[cnt+1]=p2[i];
}
printf("%d", ans+1);
return 0;
}
核心的寻找上升序列部分在导弹拦截并没有错,但不知道为什么在这题只有20pts?
机房大佬改成了这样:
#include <iostream>
#include <cstdio>
using namespace std;
int n, l, r, mid, cnt, ans;
int p1[100005], p2[100005], mp[100005], dp[100005];
int main(){
scanf("%d", &n);
for(int i=1; i<=n; i++)scanf("%d", &p1[i]), mp[p1[i]]=i;
for(int i=1; i<=n; i++)scanf("%d", &p2[i]), p2[i]=mp[p2[i]];
dp[0] = 1145141919;
for(int i=1; i<=n; i++){
l=0, r = ans + 1;
while(l<r - 1){
mid=(l+r)/2;
if(dp[mid]<p2[i]){
cnt=mid;
l=mid;
}
else r=mid;
}
ans=max(ans,l+1);
dp[l+1]=p2[i];
}
printf("%d", ans);
return 0;
}
大佬说是二分左闭右闭的问题,但我没看出来这有什么区别,玄关!!!
QwQ