It is specific to data type.
Tuples are allocated contiguously in memory. This means adding, removing or updating an element copies the whole tuple. This is ok (and often the most performant way) if you keep your tuples small.
Lists are linked lists. Prepending an element does not perform any copy, appending copies the whole list. After all, a linked list is a degenerate tree.
HashDict and HashSet are implemented similar to their Clojure variants.
Maps today copy the whole structure, unless you are updating an existing key, meaning the key space is shared and the value space is copied (as a tuple). The OTP team is working on large maps which should be available in upcoming Erlang versions which will likely use a tree approach (as in Clojure) once you reach a number of keys (12 or 16).
======
As Stuart pointed out, it is worth noting that sending messages copies the data structures, unless it is a large binary. The Erlang VM also performs many tricks to avoid copying in many places. For example, matching on a binaries creates references to the larger binary instead of copies. Multiple operations in a tuple does not copy it n-times, but only once if nothing is using the intermediate result. Data structure literals in your code live in a constant pool and are not copied at any time, etc.