Пример #1
0
        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);
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        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));
            }
        }
Пример #4
0
        /// <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);
        }