求序列的最长子序列中不可分割元素的数目。不可分割元素,肯定属于某一个最长子序列,首先做的就是把属于最长子序列的数提取出来,减小查找范围。怎么提取?可以用LIS(最长递增子序列)和LDS(最长递减子序列)。对序列,从前往后,求以每个数 a[i] 为底最长子序列数组index。从后往前,求以每个数a[i]为底的最长递减子序列数组index2。线扫一遍,如果index[i] + index2[i] == length+1(length表示最长子序列的长度),那么这个数就是属于某一个最长子序列的。
提取出来以后,对每个数a[i],看它所对应的index1[i] 在整个数组中出现几次,如果只出现一次,那么表示这个数是不可分割元素。最后输出!
#include<stdio.h> const int MAXN=100099; int n,a[MAXN],s[MAXN],index[MAXN];//序列存在s里 int lis()//单调降子序列nlogn算法 { int l,r,mid,len=1; a[1]=s[1]; index[1]=1; for(int i=2;i<=n;i++) { l=1,r=len; while(l<=r) { mid=(l+r)>>1;//除2 if(a[mid]<s[i]) l=mid+1;//不降 else r=mid-1;//二分查找 } a[l]=s[i];//插入 index[i]=l; if(l>len) len++;//增加长度 } return len; } int s2[MAXN],index2[MAXN];//序列存在s2里 int lis2()//单调不升子序列nlogn算法 { int l,r,mid,len=1; a[1]=s2[1]; index2[1]=1; for(int i=2;i<=n;i++) { l=1,r=len; while(l<=r) { mid=(l+r)>>1;//除2 if(a[mid]>s2[i]) l=mid+1;//升 else r=mid-1;//二分查找 } a[l]=s2[i];//插入 index2[i]=l; if(l>len) len++;//增加长度 } return len; } int hash[MAXN]; int main(){ int i; while(scanf("%d",&n)!=EOF){ for(i=1;i<=n;i++){ scanf("%d",&s[i]); s2[n-i+1]=s[i]; hash[i]=0; } int len=lis(); lis2(); int add=0; for(i=1;i<=n;i++){ if(index[i]+index2[n-i+1]==(len+1)){ hash[index[i]]++; } } for(i=1;i<=n;i++){ if(hash[i]==1)add++; } printf("%d ",add); } }