1

This is a standard Dynamic programming Question LIS PROBLEM

I want a longest increasing subsequence for points in 2D coordinates

that is, 2 points A(x1,y1) at index i in array , B(x2,y2) at index j in array can be a part of increasing sequence if (x1<=x2) && (y1 <=y2) && !(x1==x2 && y1==y2) && (j>i)

my code is as below which is O(N^2) using standard DP :-

#include <vector>
#include <iostream>
#include <algorithm>


using namespace std;


struct Pair
{
    int x;
    int y;
};



int main()
{

    int n;
    cin>>n;

    vector<Pair> arr;
    int L[1000000];

    Pair a;

    int i;int Maxchain=0;
    for(i=0;i<n;i++)
    {

        cin>>a.x>>a.y;
        arr.push_back(a);

        L[i]=0;
        for (int j = i-1; j >=0; j--)
        {

            if ((L[j]>(Maxchain-1))&&(L[j]>=L[i])&&(arr[j].x <= arr[i].x) && (arr[j].y <= arr[i].y) && !(arr[j].x == arr[i].x && arr[j].y == arr[i].y))
                L[i] = L[j]+1;


        }

                Maxchain = L[i]>Maxchain ?L[i]:Maxchain ;

    }
    cout<<Maxchain;

    return 0;
}

This is an O(N^2) solution can it be further reduced or any alogrithm for this to solve in O(NlogN) or O(Nlog^2N) ?

for reference found something here:

Longest Increasing Subsequence (LIS) with two numbers

The second answer is more appropriate for my case but how can we implement that?

Need a Better answer or algorithm.

Community
  • 1
  • 1
  • The very Wikipedia article you cite shows an `O(n log n)` algorithm. Does it not work for you? – Igor Tandetnik Jan 08 '17 at 15:07
  • nope its for one dimension @IgorTandetnik –  Jan 08 '17 at 16:13
  • As I understand, you do have a one-dimensional array, which contains elements that can be compared to each other. The fact that each object internally consists of a pair of numbers is irrelevant. Nothing in the algorithm requires that the objects be integers or of some other scalar type - just that they be comparable. – Igor Tandetnik Jan 08 '17 at 17:24
  • if you think care fully you will understand that deciding which one to take for selection in the LIS is tough as if i donot select an element it can be a part of LIS in some cases but I knw there is a solution with less tha O(N^2) complexity. –  Jan 08 '17 at 17:41
  • if you have 2 vairable its already two dimension as they are coordinates .. Check THis [Link](http://stackoverflow.com/questions/8716934/longest-increasing-subsequence-lis-with-two-numbers) but the answer selected is wrong and at second position is some what right but i need implementation for this in C++ with my conditions . Found recently. –  Jan 08 '17 at 17:45
  • @IgorTandetnik edited as per what I found. –  Jan 08 '17 at 17:56

1 Answers1

1

I'll assume that both coordinates are in the [0..N-1] range (if it's not the case, we can "compress" them without changing their ordering relation).

Let's take a closer look at a standard dynamic programming solution. Let f[i] be the length of the longest increasing subsequence that ends in the i-th position. A simple (but slow) way to compute it is too iterate over all previous elements and choose the optimal one. What we want to find is the max f[j] for all such j that p[j].x <= p[i].x and p[j].y <= p[j].y. It looks like some kind of a 2-D query in a rectangle (I know that there is another condition that p[j] != p[i], but we can work around it by querying two rectangles (p[i].x - 1, p[i].y) and (p[i].x, p[i].y - 1).).

So we need a data structure that supports two operations: adding a point with a specific value and getting the maximum value in a rectangle. A segment tree by x-coordinate that stores a balanced binary search tree by y-coordinate for all points in its range can do it in O(log^2 N) per query. Every query range is decomposed into at most O(log N) nodes in the tree. If it's an insertion query, we need to insert the current point (p[i].x, p[i].y) with a value f[i] into the binary search trees for each of these nodes. If it's a get maximum query, we need to get a maximum for some prefix of each of these trees. Either way, we perform an O(log N) operation for O(log N) binary search trees per query. Thus, the total time complexity is (N * log^2 N). The space complexity is O(N log N) as there are O(log N) levels in the tree and each point can occur somewhere at most once per level.

This solution already satisfies your requirements, but it looks pretty hard to code. We can slightly simplify it. We can do two "runs": during the first run, we just store the queries that go into each node of the segment tree (we don't store any extra information so far). Now we can keep a vector of all numbers that ever occur in the node and a binary index tree of the same length to keep track of a minimum for each prefix and get it efficiently (the big picture: we used the fact that we know all the queries beforehand so we can use a combination of a sorted vector and binary index tree instead of a binary search). The time and space complexity analysis is the same as above.

A short recap: we used a data structure that supports a maximum query in a rectangle and insertions of new points efficiently to speed up finding the best j for a fixed i in an O(N^2) dynamic programming solution to solve it in O(N log^2 N).

kraskevich
  • 18,368
  • 4
  • 33
  • 45
  • Can you provide demo? –  Jan 09 '17 at 04:13
  • @VenuKantSahu I don't have the code for this problem. Here's a link: https://www.topcoder.com/community/data-science/data-science-tutorials/range-minimum-query-and-lowest-common-ancestor/#Segment_Trees that explains how to build and use a segment tree. You just need to store vectors and binary index trees, not just minimums in each node. – kraskevich Jan 09 '17 at 08:44
  • @VenuKantSahu As I have said in the beginning of my answer, we can compress `x` and `y` separately without changing the ordering so that they all go to the `[0, N - 1]` range. – kraskevich Jan 09 '17 at 14:27
  • found [SPOJ problem](http://www.spoj.com/problems/LIS2/) and its solution here [solution](https://github.com/igrsk/spoj/blob/master/LIS2.cpp) almost same problem :) do you understand this code? –  Jan 09 '17 at 14:42
  • @VenuKantSahu This code is pretty hard to read. Frankly speaking, I don't. – kraskevich Jan 09 '17 at 15:05