大致题意:由于一个数列的LIS可能存在多个,问你哪些数是所有LIS都没出现的,哪些数是所有LIS都出现的。
思路:LIS要用二分的优化写nlogn的,这题问的是每个数相关的性质,所以求出两个dp,一个表示以ai为结尾LIS的长度,一个表示从ai开始的LIS的长度
当dp1[i]+dp2[i]-1!=LIS显然ai 没组成任何LIS,此时输出1
然后抓住两条不同LIS的性质,假设a[i]仅在某一条LIS上那么另一条LIS上必然有dp1[j]=dp1[i] 或dp2[j]=dp2[i]; 此时对于a[i]输出2
否则输出3
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<queue> #include<cmath> using namespace std; const int N = 1e5+100; int a[N]; int b[N]; int tp[N]; int dpf[N],dpb[N]; const int inf =0x3f3f3f3f; bool flag[N]; int vis[N]; int n; int main() { cin>>n; for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) b[i]=a[n-i+1]; memset(tp,0x3f,sizeof(tp)); int LIS=1; for(int i=1;i<=n;i++) { int * p=lower_bound(tp+1,tp+1+n,a[i]); *p=a[i]; dpf[i]=p-tp; LIS=max(LIS,dpf[i]); } memset(tp,-1,sizeof(tp));tp[0]=inf; for(int i=1;i<=n;i++) { int l=0,r=n+1; while(r-l>1) { int m=(l+r)>>1; if(tp[m]>b[i]) l=m; else r=m; } tp[l+1]=b[i]; dpb[n-i+1]=l+1; } for(int i=1;i<=n;i++) if(dpf[i]+dpb[i]-1==LIS) flag[i]=1,vis[dpf[i]]++; for(int i=1;i<=n;i++) if(flag[i]==0) printf("1"); else if(flag[i]&&vis[dpf[i]]>1) printf("2"); else printf("3"); return 0; }