Блог пользователя Easy_

Автор Easy_, 10 лет назад, По-русски

Всем привет, у меня вопрос по очень простой задаче из acmp.ru ( Преобразование последовательности — 2 )

Вот таким образом я ее пытался решить:

#include <fstream>
#include <algorithm>
#include <map>
 
#define LL long long
 
using namespace std;
 
fstream in("input.txt"), out("output.txt", ios::out);
 
int B[105], N, k, mi, mv, i;
map<int, int> A;
 
int main()
{
    in >> N;
    for(; in >> k; A[k]++, B[i++] = k)
        if(A[k] > mv)
            mv = A[k], mi = k;
        else
            if(A[k] == mv)
                mi = min(mi, k);
                 
    for(i = 0; i < N; i++)
        if(B[i] != mi)
            out << B[i] << " ";
    if(mv) 
      for(i = 0; i <= mv; i++)
        out << mi << " ";
    return 0;
}

Когда у себя на компе тестирую тесты, то выходные данные правильные, а как задачу отправляю на проверку, то сразу ошибка на первом тесте пишет. Не могу понять в чем ошибка.

Может кто-то из вас догадается? Я подозреваю, что где-то за пределы массивы выходу и т.п.

Переписал тот же алгоритм, только еще более извращенее, которое прошла все тесты:

#include <fstream>
#include <algorithm>
#include <map>
  
#define LL long long
  
using namespace std;
  
fstream in("input.txt"), out("output.txt", ios::out);
 
class Q
{
public:
    int value;
    int count;
} B[105];
 
int C[105], N, k, q, i;
map<int, int> A;
 
int CMP(const Q &a, const Q &b)
{
    return a.count > b.count;
}
 
int CMP_(const Q &a, const Q &b)
{
    return a.value < b.value;
}
 
int main()
{
    in >> N;
    for(; in >> k; A[k]++, C[i++] = k);
 
    for(i= 0; i < N; i++)
        B[i].value = C[i], B[i].count = A[C[i]];
     
    sort(B, B + N, CMP);
    sort(B, B + B[0].count, CMP_);
     
    for(i = 0; i < N; i++)
        if(C[i] != B[0].value)
            out << C[i] << " ";
             
    for(i = 0; i < B[0].count; i++)
       out << B[0].value << " ";
        
    return 0;
}
  • Проголосовать: нравится
  • +3
  • Проголосовать: не нравится

»
10 лет назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится

Я отправил свое решение которое взяло ACCEPTED, на этот раз оно получило WA1. В состояний проверки все решения получают WA1. Вся проблема в проверочной системе.

  • »
    »
    10 лет назад, # ^ |
    Rev. 4   Проголосовать: нравится 0 Проголосовать: не нравится

    Я исправил решение, вот работающий пример:

    #include <fstream>
    #include <algorithm>
    #include <map>
     
    #define LL long long
     
    using namespace std;
     
    fstream in("input.txt"), out("output.txt", ios::out);
     
    int B[105], N, k, mi, mv, i;
    map<int, int> A;
     
    int main()
    {
        in >> N;
        for(; in >> k;)
        {
            // В массиве "B" обычный массив
            // В массиве "A" i-й элемент хранит количество элементов равных i
    	A[k]++, B[i++] = k;
            if(A[k] > mv) // Нахожу элемент который встречается максимальное кол-во раз
                mv = A[k], mi = k;
            else
                if(A[k] == mv) // Если нашли элемент, который 
                  mi = min(mi, k);  //встречается столько же раз, то выбираем наименьшее из них
          }
        
      // Просто выводим массив
        for(i = 0; i < N; i++)
            if(B[i] != mi)
                out << B[i] << " ";
                
        for(i = 0; i < mv; i++)
            out << mi << " ";
        return 0;
    }
    

    Тесты этой задачи она прошла на ура.

    Там есть еще одна задача, абсолютно такая же, только входные данные могут быть больше.

    Преобразование последовательности

    Алгоритм выдает TL на 8 тесте.

    Я не могу понять, что в моем решении так замедляет алгоритм?

    Просто идет чтение из массива, и сразу же находиться числа которые встречаются максимальное количество раз.

    Далее просто вывожу массив и все.

    Может не стоит эти проверки при чтении из файла делать?

    В обсуждениях задачи смотрел, там некоторые даже сортировку использовали...

    Подскажите кто-нибудь пожалуйста в чем проблема?

    UPD: если использовать сортировку, то сложность будет O(logN * N), а у меня тут просто линейная сложность... Я попробовал проверку за цикл чтения из файла вывести:

    ...
    for(; in >> k;)
    		A[k]++, B[i++] = k;
    	
    	for(map<int, int>::iterator tt = A.begin(); tt != A.end(); tt++)
    	{
    		k = (*tt).first;
    		if(A[k] > mv)
                mv = A[k], mi = k;
            else
                if(A[k] == mv)
                    mi = min(mi, k);
    	}
    ...
    

    Не помогло, тоже самое..

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Аааа господа, подскажите пожалуйста..

      • »
        »
        »
        »
        10 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Не линейная. map<int, int> работает за логарифм (с константой). Именно из-за этого и TL-ится. Сначала замени cin / cout на scanf() / print(). Убери map<int, int> и вместо него сделай обычный массив. Но так как числа могут быть отрицательными, к ним еще надо прибавить 10^6 (таким образом все числа будут от 0 до 2 * 10^6).

        Код будет примерно таким:

        int C = 1e6; // 1000000
        scanf("%d", &n);
        for (int i = 0; i < n; i++) {
          scanf("%d", &x[i]);
          cnt[x[i] + C]++;
          if (cnt[x[i] + C] > maxCnt || (maxCnt == cnt[x[i] + C] && x[i] < minNum) {
            minNum = x[i];
            maxCnt = cnt[x[i] + C];
          }
        }
        for (int i = 0; i < n; i++) 
          if (minNum != x[i])
            printf("%d", x[i]);
        
        for (int i = 0; i < maxCnt; i++) 
          printf("%d", minNum);
        
        • »
          »
          »
          »
          »
          10 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          Седевая моя голова..

          У меня же массив "B" из 105 элементов.. Поставил B[200005] и уже TL на 18 ...

          Спасибо большое, не додумался бы до такого с массивом для отрицательных элементов..

          Сейчас попробую реализовать..

          Хотел бы узнать, что делали, если бы элементы были < |10^9| ?

          • »
            »
            »
            »
            »
            »
            10 лет назад, # ^ |
            Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

            Если бы элементы были бы до 10^9, то я бы отсортировал, и в отсортированном массиве находил бы число которое встречается макс. количество раз.

            Код такой примерно:

            sort(a, a + n);
            maxNum = a[0];
            maxCnt = 1;
            for (int i = 0; i + 1 < n; i++) {
              if (a[i] == a[i + 1]) {
                cnt++;
                if (cnt > maxCnt) {
                  maxNum = a[i];
                  maxCnt = cnt;
                }
              }
              else cnt = 1;
            }
            for (int i = 0; i < n; i++)
              if (old_a[i] != maxNum)
                printf("%d ", old_a[i]);
            
            for (int i = 0; i < maxCnt; i++) 
              printf("%d ", maxNum);
            
    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Попробуйте printf/scanf вместо потоков