private void buildLevel(int i) {
/******************************************************************************
* Find all the variables                                                      *
******************************************************************************/
	// number of nodes
	int n = tree.length;
	// height of tree
	int h = (int)Math.floor(log2(n));
	// number of nodes filled in the last level
	int A = n - (powerOf2(h) - 1);
	// the first k nodes are roots of subtrees of size k1
	int k = (int)Math.floor(A/powerOf2(h-i));
	// s is the median value
	PSTPoint s = getPoint(powerOf2(i+1));
	// the first k nodes are roots of subtrees of size k1
	int k1 = powerOf2(h+1-i) - 1;
	// the (k+1)-st node is the root of subtree of size k2
	int k2 = powerOf2(h-i) - 1 + A - k*powerOf2(h-i);
	// the remaining nodes are roots of subtrees of size k3
	int k3 = powerOf2(h-i) - 1;

/******************************************************************************
* Order nodes at given level                                                  *
******************************************************************************/

	int indexOfMaxY;

	// build the subtrees of size k1
	for(int j = 1; j <= k; j++) {
	    // Find point with maximum Y in range
	    indexOfMaxY = powerOf2(i)+(j-1)*k1;
	    for(int index = indexOfMaxY; index <= powerOf2(i)+j*k1-1; index++)
		if(getPoint(index).yGreaterThan(getPoint(indexOfMaxY)))
		    indexOfMaxY = index;
	    swap(indexOfMaxY,powerOf2(i)+j-1);
	}

	if(k < powerOf2(i)) {
	    // build the one subtree of size k2
	    indexOfMaxY = powerOf2(i)+k*k1;
	    for(int index = indexOfMaxY; index <= powerOf2(i)+k*k1+k2-1; index++) {
		if(getPoint(index).yGreaterThan(getPoint(indexOfMaxY)))
		    indexOfMaxY = index;
	    }
	    swap(indexOfMaxY,powerOf2(i)+k);
	
	    // build the subtrees of size k3
	    int m = powerOf2(i)+k*k1+k2;
	    for(int j = 1; j <= powerOf2(i)-k-1; j++) {
		indexOfMaxY = m+(j-1)*k3;
		for(int index = indexOfMaxY; index <= m+j*k3-1; index++)
		    if(getPoint(index).yGreaterThan(getPoint(indexOfMaxY)))
			indexOfMaxY = index;
		swap(indexOfMaxY,powerOf2(i)+k+j);
	    }
	}
	// Finally, sort all points past the current level
	inPlaceSort(powerOf2(i+1),n,s);
    }