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

Автор begoon, 14 лет назад, По-русски
http://acmp.ru/index.asp?main=task&id_task=433

Подскажите идею динамики. Судя по ограничению в 10^6 там требуется максимум n*log(n) решение. 

У меня пока, увы, только квадратичное, которые, ясное дело, падает с TLE:

void solve(istream& is, ostream& os) {
  int n;
  string s;
  is >> n >> s;
  vector<int> dp(n, 0);
  unsigned long long ans = 0;
  for (int i = 0; i < n; ++i) {
    dp[i] = s[i] == 'a' ? +1 : -1;
    for (int j = 0; j < i; ++j) {
      dp[j] += dp[i];
      if (dp[j] == 0)
        ans += 1;
    }
  }
  os << ans << endl;
}

Не пойму, как делать половинное деление, чтобы получить log(n), ведь приходится проверять подстроки не только в кусках с границами в 1/2, 1/4, 1/8 и т.д., но пересекающие их.

  • Проголосовать: нравится
  • 0
  • Проголосовать: не нравится

14 лет назад, # |
Rev. 3   Проголосовать: нравится +3 Проголосовать: не нравится
Воспользуйтесь методом "разделяй и властвуй". Решение для строки будет складываться из суммы решений по двум половинкам, плюс кол-во нужных подстрок, которые левым концом затрагивают левую половинку, а правым правую. Такие надо посчитать линейно, тогда общая сложность будет O(n*log(n)).

А можно и линейно решить, для этого просто нужно для каждого префикса хранить разность между количеством букв a и b и прибавлять к ответу сколько таких разностей уже было в предыдущих префиксах.
  • 14 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
    Похоже на правду. Только к ответу прибавляем количество разниц со знаком минус.

    UPD. А не.. я напутал. Со знаком плюс.
14 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
Мне кажется тут должна быть какая-то линия.. Если n*logn обычно ставят ограничения 10^5. Да к тому же 1 сек..
14 лет назад, # |
  Проголосовать: нравится +4 Проголосовать: не нравится
РОИ-2008, задача 1A
n*log(n) вполне тогда проходил. Решение:
  1. Считаем (количество букв a - количество букв b) на всех префиксах. p[x] - на диапазоне [1,x]
  2. Очевидно что если x<y и p[x]==p[y], то в диапазоне [x+1,y] букв поровну.
  3. Считаем количество значений p[x]==k для всех возможных k (nlogn если считать сортировкой или n, если считать карманной сортировкой). Теперь, пусть у нас есть l балансов k. Тогда они порождают l*(l-1)/2 вариантов.
  4. Помним про int64/long long
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Можно за линейное причем очень-очень коротко
http://acmp.ru/index.asp?main=bstatus&id_t=433
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Даже я со своим синим именем придумал как за линию написать:)
Называется частичные суммы:)
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Странно выглядит, с учетом того, что пару сообщений выше висит разбор...
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Ну я не читал, тк это очевидная задача:)
14 лет назад, # |
Rev. 2   Проголосовать: нравится -6 Проголосовать: не нравится
За линию:
1. Считаем суммы на префиксах
Можно заметить, что если сумма на двух префиксах равны. Значит между ними количество "a" и "b" равны
2. Считаем количесто префиксов суммы Х
3. Прибавляем к ответу d[X]*(d[X]-1) div 2, где d[X] - количесто префиксов суммы Х

вот мой код, если что-то непонятно
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Еще один. Нет, ну вот вы мне объясните, зачем пересказывать уже сделанный разбор?
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Не читайте. Я ваш разбор не понел
      • 14 лет назад, # ^ |
          Проголосовать: нравится -8 Проголосовать: не нравится
        1. Ваш разбор - это мой разбор в котором конкретные понятия типа "(количество букв a - количество букв b)" заменены на абстрактные типа "суммы". На мой взгляд вы даже не читали, раз не заметили даже сходства.

        2. Зачем вам массив dp?
        • 14 лет назад, # ^ |
          Rev. 2   Проголосовать: нравится +1 Проголосовать: не нравится
          Вообще то вы тоже пересказали разбор который был сделан до вас.

          К тому же сделанный за линию, без сортировки.
          • 14 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится
            1. Мое решение за nlog отличается от того. Я решил, что оно более простое и понятное, поэтому и привел его.
            2. Я конкретизировал решение того автора за линию разобрав его подробнее. Не считаю, что это особо плохо.
        • 14 лет назад, # ^ |
            Проголосовать: нравится +3 Проголосовать: не нравится
          Извените, если вам этот коммент мешает.
          • 14 лет назад, # ^ |
              Проголосовать: нравится +1 Проголосовать: не нравится
            Я понял. Вы читаете мой комментарий так: "Ну вот, пришел еще один человек, разобрал пересказав мой разбор. Задолбали уже". Его надо читать так: "Хм. Вот два комментария. Они почти идентичны. Что хотел сказать автор публикуя второй комментарий". Просто я видел подобную ситуацию уже несколько раз, а сейчас увидел практически дословное повторение. Поэтому и заинтересовался. А сообщество просто сообщает мне, что я не прав и не объясняет почему. Обидно...