若是用dp求LIS的话,记录路径是比较简单的,只要在更新dp数组的时候同时记录路径,最后找LIS长度的时候同时找到终点,经过终点逆向就能找到LIS路径了(这是我临时想的,可能有更好的方法,不保证正确性)算法
for (int i = 1; i <= n; i++) for (int j = 1; j < i; j++) if (a[j] < a[i] && f[i] < f[j] + 1){ f[i] = f[j] + 1; path[i] = j; } int s; for (int i = 1; i <= n; i++) if(ans<f[i]){ ans=f[i]; s=i; } while(s!=0){ printf("%d ",a[s]);//这是逆向输出路径 s=path[s]; }
可是用贪心+二分来求LIS时,怎么找LIS路径呢? 注意,low数组中存的并不必定是正确LIS,可是不影响求LIS长度。数组
其实这个算法记录路径也并不复杂,咱们在遍历目标数组时,数组里的每个数都是有机会进入low数组的,因此咱们构造一个pos数组,在每一个数进入low时,记录该数在low的位置,表示以该数结尾的LIS长度,原数组遍历结束后,从右往左寻找pos中的最大值,最终就会获得一个倒着的LIS序列,代码也比较好理解spa
low[1] = a[1]; int len = 1; pos[1] = len; for (int i = 2; i <= n; i++) { if (a[i] >= low[len])//严格上升的话不能等 { low[++len] = a[i]; pos[i] = len; } else { int index = lower_bound(low + 1, low + 1 + len, a[i]) - low; low[index] = a[i]; pos[i] = index; } } int maxx = INF, tem = len; for (int i = n; i >= 1; i--) { if (tem == 0) break; if (pos[i] == tem && maxx >= a[i])//严格上升的话是'>' { tem--; maxx = a[i]; } }