There's two important areas to consider for efficient rendering of large landscapes with lots of objects. One is to minimize redundant work by only drawing what is visible from the current camera angle and the other is to maximize the efficiency of rendering what is visible.
There are two main ways to minimize redundant rendering work. First you want to avoid drawing anything that is outside the field of view of the camera. This visibility culling can be accelerated using a variety of data structures: octrees, quadtrees, sphere trees, bsp trees (generally more suited to less open environments rather than landscapes), etc. Some kind of hierarchical scene arrangement is also useful in accelerating this kind of culling. The same data structures can also be used to skip rendering of objects below a certain size threshold on screen.
Second you want to avoid rendering objects that are occluded by nearer objects. There are many different techniques for occlusion culling, some using GPU acceleration through occlusion queries and others operating entirely on the CPU. The value of occlusion culling will depend somewhat on your typical camera angles, terrain roughness and the size of objects on the terrain. A relatively flat, open terrain with only small objects or a camera that looks mostly down at the ground rather than out towards the horizon will reduce opportunities for occlusion culling. Some hierarchical organization of your scene will again help with occlusion culling as if a parent object is occluded you can skip tests for it's children.
Once you've minimized the set of objects that need to be rendered you can turn your attention to maximizing rendering efficiency for the objects that are visible. Level of detail techniques are useful here (lower poly meshes for distant objects). The impostor technique mentioned in another answer is another approach that can be useful, replacing complex geometry with simple billboards. Various approaches to instancing geometry are also worth pursuing - modern graphics hardware can render many copies of the same geometry with different positions and other variations with a single call to the graphics API. Finally all the standard techniques for efficient use of graphics hardware apply here: sorting for maximum rendering efficiency (somewhat hardware dependent), minimizing redundant work per frame, packing geometry efficiently, optimizing vertex and pixel shaders, etc.
Each of the areas mentioned are quite complex in themselves and there are many papers, books and articles elaborating on the details. Hopefully the techniques mentioned here are enough to point you in the right direction for some google research.