Сверху вниз, да, а как же еще? =) Одним из рабочих вариантов был
R-Tree
Хотя, по-хорошему, R-Tree стоит использовать только для статичных объектов, иначе его приходится все время перестраивать.
Чтобы все время не перестраивать дерево, можно разделить объекты по признаку "двигается / не двигается". Соответственно, все статичные объекты складывать в дерево, все динамичные - хранить отдельным списком. Ну и проводить 2 поиска, по статичным и по динамичным. Но все это весьма и весьма привязано к конкретным условиям в приложении, не является "серебряной пулей".