Быстрое решение для кода, который вы опубликовали до сих пор. Измените
vec.push_back(new Y);
vec[i]->x = ...;
vec[i]->y = ...; // error
на
Y* newy = new Y;
vec.push_back(newy);
newy->x = ...;
newy->y = ...; // no error
Но тогда вам все равно понадобится приведение X * к Y * при чтении объекта обратно для доступа к переменным-членам, содержащимся только в Y.
if(condition)
cout << static_cast<Y*>(vec[i])->y;
Вместо приведений можно также создать отдельные векторы для X и Y (указатели не обязательно должны быть, если они содержат только один тип, но также могут быть указатели) и просто заполнить и получить доступ к одному из них.
vector<X> vecX;
vector<Y> vecY;
bool condition;