What’s an efficient way to change the post status of many posts at once?

What you are doing is the safe way, and the way I’d recommend. To my knowledge, there is no Core function to bulk update only single values in the $wpdb->posts table, so to do that you’d need to write your own SQL…

$ids = array(); // your IDs; I am assuming these to be validated and sanitized
$wpdb->query("UPDATE {$wpdb->posts} SET post_status="publish" WHERE ID IN  (".implode(',',$ids)).")");

You might be able to do the same with $wpdb->update but I rarely use that method, so I am not sure. (A comment below indicates that it is not possible.) Check the Codex and play with it if you want.

I would recommend not doing either, though, and continuing to use wp_update_post. If you skip around the Core functions you also skip around numerous actions and filters, and may cause yourself unintended consequences or other frustrations later on.