此思路详见luogu第一个题解 一个很妙的离散化
刘汝佳蓝书上面的LIS 详见蓝书
d[i]以i为结尾的最长上升子序列的长度 g[i]表示d值为i的最小状态的编号即长度为i的上升子序列的最小末尾值
1 for(int i=1;i<=n;++i) scanf("%d",&a[i]); 2 for(int i=1;i<=n;++i) 3 { 4 int k=lower_bound(g+1,g+1+n,a[i])-g; 5 d[i]=k; 6 g[k]=cb[i]; 7 }
只是手写二分的时候要注意超多细节 巨难受
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define rg register 4 const int N=100000+5,inf=0x3f3f3f3f; 5 int n,a[N],b[N],ca[N],cb[N]; 6 int g[N],d[N],len=0; 7 8 template<class t>void rd(t &x) 9 { 10 x=0;int w=0;char ch=0; 11 while(!isdigit(ch)) w|=ch=='-',ch=getchar(); 12 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 13 x=w?-x:x; 14 } 15 16 int main() 17 { 18 rd(n); 19 memset(g,inf,sizeof(g)); 20 for(rg int i=1;i<=n;++i) rd(a[i]),ca[a[i]]=i; 21 for(rg int i=1;i<=n;++i) rd(b[i]),cb[i]=ca[b[i]]; 22 for(rg int i=1;i<=n;++i) 23 { 24 int k=lower_bound(g+1,g+1+n,cb[i])-g; 25 g[k]=cb[i]; 26 len=max(len,k); 27 } 28 printf("%d",len); 29 return 0; 30 }100昏 用lower_bound
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define rg register 4 const int N=100000+5,inf=0x3f3f3f3f; 5 int n,a[N],b[N],ca[N],cb[N]; 6 int g[N],len=0; 7 8 template<class t>void rd(t &x) 9 { 10 x=0;int w=0;char ch=0; 11 while(!isdigit(ch)) w|=ch=='-',ch=getchar(); 12 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 13 x=w?-x:x; 14 } 15 16 int find(int x) 17 { 18 int l=1,r=len,mid; 19 while(l<=r) 20 { 21 mid=(l+r)>>1; 22 if(x>g[mid]) l=mid+1; 23 else r=mid-1; 24 } 25 return l; 26 } 27 28 int main() 29 { 30 rd(n); 31 memset(g,inf,sizeof(g)); 32 for(rg int i=1;i<=n;++i) rd(a[i]),ca[a[i]]=i; 33 for(rg int i=1;i<=n;++i) rd(b[i]),cb[i]=ca[b[i]]; 34 for(rg int i=1;i<=n;++i) 35 { 36 int k=find(cb[i]); 37 g[k]=cb[i]; 38 len=max(len,k); 39 } 40 printf("%d",len); 41 return 0; 42 }100昏 手写二分