Почему segmentation fault то появляется, то исчезает?

Решал такую задачу: Девочка Грета занимается исследованиями в области глобального потепления. Грета замеряла температуру на улице в течение N дней. Теперь ей интересна следующая статистика: для каждой температуры в интервале [−T;T] узнать номера дней, в которые держалась данная температура.

Входные данные
В первой строке входных данных содержатся два натуральных числа: T и N (T≤60, N≤1000). В следующей строке содержатся N целых чисел, по модулю не превосходящих 100 — измерение температуры в каждый из дней. Дни нумеруются с единицы.

Выходные данные
Выведите 2T+1 строк. Каждая строка должна содержать данные о днях, в которые держалась данная температура. Используйте формат вывода в соответствии с примером. Температуры необходимо выводить в порядке от меньшей к большей. Дни для каждой температуры необходимо выводить в порядке возрастания.

Вот мой код:

#include <iostream>
#include <vector>
using namespace std;
 
int main()
{
    int t, n;
    cin >> t >> n;
    vector <vector <int> > ans(2*t + 1);
    for (int i = 1; i <= n; ++i) {
        int temp;
        cin >> temp;
        ans[temp + t].push_back(i);
    }
    for (int temp = 0; temp <= 2*t; ++temp) {
        cout << temp - t << ": ";
        for (int j = 0; j < ans[temp].size(); ++j) {
            cout << ans[temp][j] << " ";
        }
        cout << endl;
    }
    return 0;
}

Вопрос заключается в том, что когда я ввожу например:

5 10
2 -6 0 4 4 0 -4 -5 -3 2

То дальше программа либо выводит результат:

-5: 8 
-4: 7 
-3: 9 
-2: 
-1: 
0: 3 6 
1:
2: 1 10 
3: 
4: 4 5 
5: 

Любо segmentation fault. Из-за чего в данном случае происходит segmentation fault, и почему при одних и тех же входных данных в одних случаях мы получаем ошибку, а в других нет?


Ответы (2 шт):

Автор решения: DmitryK

Вы видимо хотели иметь вектор, в котором будет вектор из 2 значений - номер дня и температура в этот день. Тогда вы немного неправильно вносите данные, должно быть вот так:

for (int i = 1; i <= n; ++i) 
    {
        int temp;
        cin >> temp;
        ans.push_back({ i, temp});
    }

Но как написал @Harry from Kiev в данном случае лучше использовать вектор пар, или вектор собственной структуры из 2 элементов.

struct Day
{ int day;
  int temp;
}
vector<Day> ans(2*t + 1);
// или
vector< pair<int,int> > ans(2*t + 1);

Если дальше смотреть условия вашей задачи, то болеее оптимальным будет использование вместо vector<> контейнера map<> (или multimap<>, если температура может повторяться), который хранит пары из ключа и значения. Тогда ключом будет температура, а значением - номер дня. В этом случае и сортировка сразу происходит - в map<> данные хранятся в отсортированном виде.

map<int,int> ans;
for (int i = 1; i <= n; ++i) 
    {
        int temp;
        cin >> temp;
        ans[temp] = i; // если элемента с таким ключом нет, то он вставляется
    }

→ Ссылка
Автор решения: DmitryK

нужно создать вектор который в свою очередь состоит из векторов произвольной длины(температура и произвольное количество дней, в которые была данная температура). И сделать это нужно пользуясь минимумом инструментов, т.е самим вектором и циклом for, не прибегая к использованию вектора собственной структура и контейнеру map.
Тогда так: первый вектор будет из 201 элемента vector <vector > ans(201) - температура от -100 до 100 и плюс 0. А в конечных векторах - номера дней. Тогда чтобы обращаться по температуре как по индексу нужно добавлять к температуре 100 - тогда в ans[0] будет храниться массив дней для температуры -100, в ans[100] - для температуры 0, в ans[200] для температуры +100:

vector <vector <int> > ans(201);
for (int i = 1; i <= n; ++i) 
{
   int temp;
   cin >> temp;
   ans[temp + 100].push_back(i);
}

И всё-таки проверяйте вводимые значения на корректность условиям задачи. Т.е. вводимые температуры должны лежать в диапазоне -100 < temp < +100. Иначе т.к. значение температуры используется как индекс, при некорректном вводе всё равно будет выход за границы массива и неопределенное поведение программы.

→ Ссылка