Basic OpenGL drawing shapes
For the most part this looks like a typical way to draw geometry in OpenGL. I see a few things that could be improved.
Use structures for structured data
Currently you're storing your vertex coordinates in a 1 dimensional array of floats. But that data isn't just 6 floats. It's 3 points. So you should create a point structure:
struct Point2D {
    float x;
    float y;
};

And your vertex coordinates should be defined using that struct:
struct Point2D triangle1[] = {
    { 0.0f, 0.0f },
    { 1.0f, -1.0f },
    { -1.0f, -1.0f }
};

struct Point2D triangle2[] = {
    { 0.0f, 1.0f },
    { 1.0f, 0.0f },
    { -1.0f, 0.0f }
};

This will make it easier to read and understand. It also makes it much easier to find bugs. If your geometry looks weird, and it turns out you missed an x coordinate in one vertex, good luck figuring out that's the problem with a 1D array of floats. If you miss a coordinate with this struct, you'll get a compiler error.
And since you're working with triangles in this case, you could even make a Triangle2D structure containing 3 Point2Ds. It might be overkill for this simple example, though.
Use meaningful variable names
Names like vao and vbo tell you that those variables store the names for vertex array objects and vertex buffer objects. But they don't tell you which object in your scene they're used for, or how they differ from any other vertex array or buffer you're going to allocate later in the code. Obviously in this example, they only represent the arrays/buffers for the 2 triangles you're drawing, so suggesting a better name is difficult. But at least something like triArrayObj and triBufferObj would be more clear. In a game, for example, you might keep one set around for the scenery and another for the player's character, and another for an enemy, or something like that. They should be named as such.
The names of vec and vec2 are even worse, though. They're vectors, but vectors of what? As with the VAOs and VBOs, there's no real meaning in this particular code since it's just an example, so I'd at least name them tri1 and tri2 for &quot;Triangle 1&quot; and &quot;Triangle 2&quot;.
Don't use sleep
You should not be calling sleep() in this code. It's not clear what you're trying to accomplish by doing that. It looks like you're drawing a frame with 1 triangle, then clearing it and drawing a frame with another triangle. Normally, you'd have an event driven application that takes input from the user and tells you to draw with some period, so you wouldn't want to use sleep() because you'd slow it down.
Efficiency
You ask a fair question about whether the way you're doing things is efficient or not. It's a little hard to answer given the simplicity of your example, but here are my thoughts.
In general you want to generate OpenGL objects like vertex array objects and vertex buffer objects infrequently. Allocating memory takes time. You also want to minimize sending data to the GPU. What that means in general is allocate whatever you can upfront and load it onto the GPU as infrequently as possible. In many cases you have a large amount of geometry that won't change, and a little bit of geometry that will change. You might also have a set of textures that are used throughout your rendering. If you can load all your unchanging geometry and unchanging textures onto the card at the start of your app (or assuming it's a game, the start of a level), that will help minimize the overhead of sending data to the GPU.
But you have to be careful. If you load more data onto the GPU than you have memory for, you could get VRAM swapping, or even just rendering errors. It's often the case that all the data you need to draw a scene won't fit on the GPU at once and you have no choice but to upload some of it every frame, or in severe cases, multiple times per frame.
You may find this becomes more difficult than it sounds at first as you attempt to support a wider range of possible GPUs. Your users may have hardware that ranges from extremely low-end to extremely high-end.