private static int GetLongestMonotoneSubsequenceLengthNaive <T>(IList <T> sequence, MonotoneType monotoneType) where T : IComparable <T> { int n = sequence.Count, res = 0; var dp = new int[n]; for (int i = 0; i < n; i++) { dp[i] = 1; for (int j = 0; j < i; j++) { switch (monotoneType) { case MonotoneType.Increasing: if (sequence[i].CompareTo(sequence[j]) > 0) { dp[i] = Math.Max(dp[i], dp[j] + 1); } break; case MonotoneType.Decreasing: if (sequence[i].CompareTo(sequence[j]) < 0) { dp[i] = Math.Max(dp[i], dp[j] + 1); } break; case MonotoneType.NonDecreasing: if (sequence[i].CompareTo(sequence[j]) >= 0) { dp[i] = Math.Max(dp[i], dp[j] + 1); } break; case MonotoneType.NonIncreasing: if (sequence[i].CompareTo(sequence[j]) <= 0) { dp[i] = Math.Max(dp[i], dp[j] + 1); } break; default: throw new System.Exception("Unknown monotone type"); } } res = Math.Max(res, dp[i]); } return(res); }
/// <summary> /// Gets the length of the longest monotone subsequence with a given type of monotonicity /// Time complexity: O(NlogN) /// </summary> public static int GetLongestMonotoneSubsequenceLength <T>(System.Collections.Generic.IEnumerable <T> sequence, MonotoneType monotoneType) where T : IComparable <T> { var minElements = new System.Collections.Generic.List <T>(); foreach (var element in sequence) { int l = -1, r = minElements.Count; while (l + 1 < r) { int m = (l + r) / 2; switch (monotoneType) { case MonotoneType.Increasing: if (minElements[m].CompareTo(element) < 0) { l = m; } else { r = m; } break; case MonotoneType.Decreasing: if (minElements[m].CompareTo(element) > 0) { l = m; } else { r = m; } break; case MonotoneType.NonDecreasing: if (minElements[m].CompareTo(element) > 0) { r = m; } else { l = m; } break; case MonotoneType.NonIncreasing: if (minElements[m].CompareTo(element) < 0) { r = m; } else { l = m; } break; default: throw new System.Exception("Unknown monotone type"); } } if (r == minElements.Count) { minElements.Add(element); } else { minElements[r] = element; } } return(minElements.Count); }
void DoMonotoneTest(MonotoneType monotoneType) { int n = 8; var p = PermutationUtils.First(n); do { var copyP = (int[])p.Clone(); var my = SequenceUtils.GetLongestMonotoneSubsequenceLength(copyP, monotoneType); Assert.IsTrue(p.SequenceEqual(copyP)); var correct = GetLongestMonotoneSubsequenceLengthNaive(p, monotoneType); Assert.AreEqual(correct, my); var mlist = SequenceUtils.GetLongestMonotoneSubsequence(copyP, monotoneType); Assert.IsTrue(p.SequenceEqual(copyP)); Assert.AreEqual(my, mlist.Length); for (int i = 1; i < mlist.Length; ++i) { Assert.IsTrue(mlist[i] >= 0 && mlist[i] < n); Assert.IsTrue(mlist[i] > mlist[i - 1]); switch (monotoneType) { case MonotoneType.Increasing: Assert.IsTrue(p[mlist[i]] > p[mlist[i - 1]]); break; case MonotoneType.Decreasing: Assert.IsTrue(p[mlist[i]] < p[mlist[i - 1]]); break; case MonotoneType.NonDecreasing: Assert.IsTrue(p[mlist[i]] >= p[mlist[i - 1]]); break; case MonotoneType.NonIncreasing: Assert.IsTrue(p[mlist[i]] <= p[mlist[i - 1]]); break; default: throw new System.Exception("Unknown monotone type"); } } } while (PermutationUtils.Next(p)); var rnd = new Random(123); for (int times = 0; times < 100; ++times) { n = rnd.Next(50) + 10; p = new int[n]; for (int i = 0; i < n; i++) { p[i] = rnd.Next(20); } var correct = GetLongestMonotoneSubsequenceLengthNaive(p, monotoneType); var my = GetLongestMonotoneSubsequenceLengthNaive(p, monotoneType); Assert.AreEqual(correct, my); n = 8; p = new int[n]; for (int i = 0; i < n; i++) { p[i] = rnd.Next(5); } Array.Sort(p); do { correct = GetLongestMonotoneSubsequenceLengthNaive(p, monotoneType); my = GetLongestMonotoneSubsequenceLengthNaive(p, monotoneType); Assert.AreEqual(correct, my); } while (PermutationUtils.Next(p)); } }
/// <summary> /// Gets the longest monotone subsequence with a given type of monotonicity /// Returns not the subsequence itself, but the sequence of positions of elements. /// Time complexity: O(NlogN) /// /// WARNING: Allocates additional O(N) space /// </summary> public static int[] GetLongestMonotoneSubsequence <T>(System.Collections.Generic.IList <T> sequence, MonotoneType monotoneType) where T : IComparable <T> { var prev = new int[sequence.Count]; var minElements = new System.Collections.Generic.List <T>(); var minElementsPositions = new System.Collections.Generic.List <int>(); for (int i = 0; i < sequence.Count; ++i) { var element = sequence[i]; int l = -1, r = minElements.Count; while (l + 1 < r) { int m = (l + r) / 2; switch (monotoneType) { case MonotoneType.Increasing: if (minElements[m].CompareTo(element) < 0) { l = m; } else { r = m; } break; case MonotoneType.Decreasing: if (minElements[m].CompareTo(element) > 0) { l = m; } else { r = m; } break; case MonotoneType.NonDecreasing: if (minElements[m].CompareTo(element) > 0) { r = m; } else { l = m; } break; case MonotoneType.NonIncreasing: if (minElements[m].CompareTo(element) < 0) { r = m; } else { l = m; } break; default: throw new System.Exception("Unknown monotone type"); } } if (r == minElements.Count) { minElements.Add(element); minElementsPositions.Add(i); } else { minElements[r] = element; minElementsPositions[r] = i; } if (r > 0) { prev[i] = minElementsPositions[r - 1]; } else { prev[i] = -1; } } var ans = new int[minElements.Count]; int curPosition = minElementsPositions[minElementsPositions.Count - 1], curLength = minElements.Count; while (curPosition != -1) { ans[--curLength] = curPosition; curPosition = prev[curPosition]; } return(ans); }