static int mmImpl(Point[]A, int i, int j, int k) {
		if (i==j) return i;
		int n=j-i+1, m=(n+4)/5;
		Point[]mid = new Point[m];
		for(int l=i,t=0;l<=j;l+=5,++t) {
			if (j-l>=4) {
				Arrays.sort(A, l, l+5);
				mid[t]=A[l+2];
			} else {
				Arrays.sort(A, l, j+1);
				mid[t]=A[l+(j-l+1)/2];
			}
		}
		int p=i,midp=mmImpl(mid, 0, mid.length-1, mid.length/2);
		for (int t=i;t<=j;++t) if (A[t].compareTo(mid[midp])==0){p=t;break;} 
		swap(A, i, p);
		int s,l=i+1; Point pivot=mid[midp];
		for (int t=i+1;t<=j;++t)
			if (A[t].compareTo(pivot)>=0) swap(A, l++, t);
		swap(A, i, l-1);
		if ((s=l-i)==k) return l-1;
		else if (s>k) return mmImpl(A, i, l-2, k);
		else return mmImpl(A, l, j, k-s);
	}