/*package whatever //do not write package name here */ import java.io.*; import java.util.*; class GFG { static final int MAX = 1000; // Constructs a segment tree and stores tree[] static void buildTree(int treeIndex, int l, int r, List<Pair<Integer, Integer> > a, List<List<Integer> > tree) { /* l => start of range, r => ending of a range treeIndex => index in the Segment Tree/Merge Sort Tree */ /* leaf node */ if (l == r) { tree.get(treeIndex).add(a.get(l).second); return; } int mid = (l + r) / 2; /* building left subtree */ buildTree(2 * treeIndex, l, mid, a, tree); /* building right subtree */ buildTree(2 * treeIndex + 1, mid + 1, r, a, tree); /* merging left and right child in sorted order */ List<Integer> leftChild = tree.get(2 * treeIndex); List<Integer> rightChild = tree.get(2 * treeIndex + 1); List<Integer> currentTree = new ArrayList<>(); int leftIndex = 0, rightIndex = 0; while (leftIndex < leftChild.size() && rightIndex < rightChild.size()) { if (leftChild.get(leftIndex) < rightChild.get(rightIndex)) { currentTree.add(leftChild.get(leftIndex)); leftIndex++; } else { currentTree.add(rightChild.get(rightIndex)); rightIndex++; } } while (leftIndex < leftChild.size()) { currentTree.add(leftChild.get(leftIndex)); leftIndex++; } while (rightIndex < rightChild.size()) { currentTree.add(rightChild.get(rightIndex)); rightIndex++; } tree.set(treeIndex, currentTree); } // Returns the Kth smallest number in query range static int queryRec(int segmentStart, int segmentEnd, int queryStart, int queryEnd, int treeIndex, int K, List<List<Integer> > tree) { /* segmentStart => start of a Segment, segmentEnd => ending of a Segment, queryStart => start of a query range, queryEnd => ending of a query range, treeIndex => index in the Segment Tree/Merge Sort Tree, K => kth smallest number to find */ if (segmentStart == segmentEnd) return tree.get(treeIndex).get(0); int mid = (segmentStart + segmentEnd) / 2; // finds the last index in the segment // which is <= queryEnd List<Integer> leftChild = tree.get(2 * treeIndex); int last_in_query_range = upperBound(leftChild, queryEnd); // finds the first index in the segment // which is >= queryStart int first_in_query_range = lowerBound(leftChild, queryStart); int M = last_in_query_range - first_in_query_range; if (M >= K) { // Kth smallest is in left subtree, // so recursively call left subtree for Kth // smallest number return queryRec(segmentStart, mid, queryStart, queryEnd, 2 * treeIndex, K, tree); } else { // Kth smallest is in right subtree, // so recursively call right subtree for the // (K-M)th smallest number return queryRec(mid + 1, segmentEnd, queryStart, queryEnd, 2 * treeIndex + 1, K - M, tree); } } static int query(int queryStart, int queryEnd, int K, int n, List<Pair<Integer, Integer> > a, List<Integer>[] tree) { return queryRec(0, n - 1, queryStart - 1, queryEnd - 1, 1, K, tree); } public static void main(String[] args) { int[] arr = { 3, 2, 5, 1, 8, 9 }; int n = arr.length; // vector of pairs of form {element, index} List<Pair<Integer, Integer> > v = new ArrayList<Pair<Integer, Integer> >(); for (int i = 0; i < n; i++) { v.add(new Pair<Integer, Integer>(arr[i], i)); } // sort the vector Collections.sort( v, new Comparator<Pair<Integer, Integer> >() { public int compare(Pair<Integer, Integer> a, Pair<Integer, Integer> b) { return a.getKey().compareTo(b.getKey()); } }); // Construct segment tree in tree[] List<Integer>[] tree = new List[n * 4]; for (int i = 0; i < n * 4; i++) { tree[i] = new ArrayList<Integer>(); } buildTree(1, 0, n - 1, v, tree); // Answer queries // kSmallestIndex hold the index of the kth smallest // number int kSmallestIndex = query(2, 5, 2, n, v, tree); System.out.println(arr[kSmallestIndex]); kSmallestIndex = query(1, 6, 4, n, v, tree); System.out.println(arr[kSmallestIndex]); } }