Изменение контейнера во время его итерации не является тривиальной операцией. Когда вы стираете текущий итератор , он больше не является действительным итератором. Это создает несовместимую операцию после ее удаления:
list<int> l;
for (int i = 0; i < 10; i++) l.push_back(i);
for (auto it = l.begin(); it != l.end(); )
l.erase(it);
После удаления текущего итератора:
- текущий итератор становится недействительным
- Место текущий занимает элемент следующий в списке (++).
Этот не вызывает ошибку:
list<int> l;
for (int i = 0; i < 10; i++) l.push_back(i);
for (auto it = l.begin(); it != l.end(); )
l.erase(it++)
Обратите внимание, что вы не можете сделать это с вектором. Но с векторами вы можете сделать это:
vector<int> v = {1,2,3,4,5,6,7,8,9,0};
int current_position = 0;
for (auto it = v.begin(); it != v.end(); it = v.begin() + current_position)
{
//some logic there in current position which can change
v.erase(it);
}
Еще более сложные вещи идут с картами и деревьями. Так вот, как вы должны стереть: list.erase (itt ++);
Кроме того, ваш код - небольшая ставка по сравнению с инженерным:
int main()
{
int t;
cin >> t;
while (t--)
{
ll n;
cin >> n;
set<int> list;
vector<ll> vec;
for (size_t i = 1; i <= n; i++) list.insert(i);
bool more = true;
if (list.size() == 1)
{
cout << "1 1" << endl;
continue;
}
while (list.size() > 1)
{
vec.clear();
auto it = list.begin();
vec.push_back(*it);
ll num = *it;
list.erase(it);
for (auto itt = list.begin(); itt != list.end(); )
{
if (checkPrime(*itt) || gcd(num, *itt) == 1)
{
vec.push_back(*itt);
num = *itt;
list.erase(itt++);
}
else itt++;
}
if (vec.size() == 1)
cout << "2 1" << num << endl;
else
{
cout << vec.size() << " ";
for (auto n : vec) cout << n << " ";
cout << endl;
}
}
}
return 0;
}