Problem p02618 (C++)

Buggy submission (status: Time Limit Exceeded):
#if 1
#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <cstdint>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

template <typename T, typename U>
std::enable_if_t<std::rank<T>::value == 0> fill_all(T &arr, const U &v) {
  arr = v;
}
template <typename ARR, typename U>
std::enable_if_t<std::rank<ARR>::value != 0> fill_all(ARR &arr, const U &v) {
  for (auto &i : arr) {
    fill_all(i, v);
  }
}

auto &in = std::cin;
auto &out = std::cout;
#define all_range(C) std::begin(C), std::end(C)
const double PI =
    3.141592653589793238462643383279502884197169399375105820974944;

int32_t D;
int32_t C[30];
int32_t S[400][30];

int32_t res[400];
void greedy1() {
  int32_t last[40] = {};
  fill_all(last, -1);
  for (int32_t d = 0; d < D; d++) {
    int32_t max = S[d][0];
    int32_t max_index = 0;
    for (int32_t i = 0; i < 26; i++) {
      auto ss = S[d][i] + C[i] * (d - last[i]);
      if (max < ss) {
        max = ss;
        max_index = i;
      }
    }
    res[d] = max_index;
    last[max_index] = d;
  }
}

int numofbits5(uint32_t bits) {
  bits = (bits & 0x55555555) + (bits >> 1 & 0x55555555);
  bits = (bits & 0x33333333) + (bits >> 2 & 0x33333333);
  bits = (bits & 0x0f0f0f0f) + (bits >> 4 & 0x0f0f0f0f);
  bits = (bits & 0x00ff00ff) + (bits >> 8 & 0x00ff00ff);
  return (bits & 0x0000ffff) + (bits >> 16 & 0x0000ffff);
}

int32_t bittoindex[1 << 26];
void greedy2_init() {
  for (size_t i = 0; i < 26; i++) {
    bittoindex[1 << i] = i;
  }
}
inline int bittoindexf(int32_t bit) {
  switch (bit) {
#define bittoindexf_MACRO(i)                                                   \
  case (1 << i):                                                               \
    return i;

    bittoindexf_MACRO(0);
    bittoindexf_MACRO(1);
    bittoindexf_MACRO(2);
    bittoindexf_MACRO(3);
    bittoindexf_MACRO(4);
    bittoindexf_MACRO(5);
    bittoindexf_MACRO(6);
    bittoindexf_MACRO(7);
    bittoindexf_MACRO(8);
    bittoindexf_MACRO(9);
    bittoindexf_MACRO(10);
    bittoindexf_MACRO(11);
    bittoindexf_MACRO(12);
    bittoindexf_MACRO(13);
    bittoindexf_MACRO(14);
    bittoindexf_MACRO(15);
    bittoindexf_MACRO(16);
    bittoindexf_MACRO(17);
    bittoindexf_MACRO(18);
    bittoindexf_MACRO(19);
    bittoindexf_MACRO(20);
    bittoindexf_MACRO(21);
    bittoindexf_MACRO(22);
    bittoindexf_MACRO(23);
    bittoindexf_MACRO(24);
    bittoindexf_MACRO(25);
#undef bittoindexf_MACRO
  default:
    return 0;
  }
}
int32_t dp[1 << 27];
void greedy2(int start, int base) {
  constexpr int MAX_BIT = 26;
  constexpr int DIFFBASE = 0;
  auto CC = C + start;
  auto SS = S + start;

  fill_all(dp, 0);
  for (int32_t mask = 0; mask < (1 << MAX_BIT); mask++) {
    auto d = numofbits5(mask);
    auto tmp = ~mask;
    auto bit = tmp & -tmp;
    tmp ^= bit;
    while (bit < (1 << MAX_BIT)) {
      auto index = bittoindexf(bit);
      auto next = mask | bit;
      auto add = SS[d][index] +
                 CC[index] * (DIFFBASE + d) * (DIFFBASE + d) / 2 +
                 (26 + DIFFBASE - d) * (26 + DIFFBASE - d) / 2;
      dp[next] = std::max(dp[next], dp[mask] + add);

      bit = tmp & -tmp;
      tmp ^= bit;
    }
  }

  auto R = res + start;
  int32_t now = (1 << MAX_BIT) - 1;
  while (now > 0) {
    auto d = numofbits5(now) - 1;
    auto tmp = now;
    auto bit = tmp & -tmp;
    tmp ^= bit;
    while (bit < (1 << MAX_BIT)) {
      auto index = bittoindexf(bit);
      auto next = now ^ bit;
      auto add = SS[d][index] +
                 CC[index] * (DIFFBASE + d) * (DIFFBASE + d) / 2 +
                 (26 + DIFFBASE - d) * (26 + DIFFBASE - d) / 2;
      if (dp[now] == dp[next] + add) {
        R[d] = base + index;
        break;
      }

      bit = tmp & -tmp;
      tmp ^= bit;
    }

    now ^= bit;
  }
}
#include <chrono>
auto startTime = std::chrono::system_clock::now();
void greedy3() {
  while ((std::chrono::system_clock::now() - startTime) <
         std::chrono::milliseconds(1900))
    for (size_t COUNT = 0; COUNT < 125; COUNT++)
      for (int32_t i = 0; i < D; i++) {
        int lefti = i - 1;
        while (lefti >= 0 && res[lefti] != res[i]) {
          --lefti;
        }
        int righti = i + 1;
        while (righti < D && res[righti] != res[i]) {
          ++righti;
        }

        for (int32_t j = std::max(0, i - 26); j < D && j <= i + 26; j++) {
          if (i == j) {
            continue;
          }
          if (res[i] == res[j] && i < j) {
            break;
          }
          if (res[i] == res[j]) {
            continue;
          }

          int leftj = j - 1;
          while (leftj >= 0 && res[leftj] != res[j]) {
            --leftj;
          }
          int rightj = j + 1;
          while (rightj < D && res[rightj] != res[j]) {
            ++rightj;
          }

          if (std::max(lefti, leftj) <= std::min(i, j) &&
              std::max(i, j) <= std::min(righti, rightj)) {
            auto now =
                S[i][res[i]] - C[res[i]] * (i - lefti - 1) * (i - lefti) / 2 -
                (righti == D
                     ? 0
                     : C[res[i]] * (righti - i - 1) * (righti - i) / 2) +
                S[j][res[j]] - C[res[j]] * (j - leftj - 1) * (j - leftj) / 2 -
                (rightj == D ? 0
                             : C[res[j]] * (rightj - j - 1) * (rightj - j) / 2);
            auto next =
                S[j][res[i]] - C[res[i]] * (j - lefti - 1) * (j - lefti) / 2 -
                (righti == D
                     ? 0
                     : C[res[i]] * (righti - j - 1) * (righti - j) / 2) +
                S[i][res[j]] - C[res[j]] * (i - leftj - 1) * (i - leftj) / 2 -
                (rightj == D ? 0
                             : C[res[j]] * (rightj - i - 1) * (rightj - i) / 2);

            if (now < next) {
              std::swap(res[i], res[j]);

              lefti = i - 1;
              while (lefti >= 0 && res[lefti] != res[i]) {
                --lefti;
              }
              righti = i + 1;
              while (righti < D && res[righti] != res[i]) {
                ++righti;
              }
            }
          }
        }
        if (COUNT == 490)
          for (size_t cc = 0; i < 26; i++) {
            if (res[i] == cc) {
              continue;
            }

            int leftj = i - 1;
            while (leftj >= 0 && res[leftj] != cc) {
              --leftj;
            }
            int rightj = i + 1;
            while (rightj < D && res[rightj] != cc) {
              ++rightj;
            }

            auto now =
                S[i][res[i]] - C[res[i]] * (i - lefti - 1) * (i - lefti) / 2 -
                (righti == D
                     ? 0
                     : C[res[i]] * (righti - i - 1) * (righti - i) / 2) -
                (rightj == D
                     ? 0
                     : C[cc] * (rightj - leftj - 1) * (rightj - leftj) / 2);
            auto next =
                S[i][cc] - C[cc] * (i - leftj - 1) * (i - leftj) / 2 -
                (rightj == D ? 0
                             : C[cc] * (rightj - i - 1) * (rightj - i) / 2) -
                (righti == D
                     ? 0
                     : C[res[i]] * (righti - lefti - 1) * (righti - lefti) / 2);

            if (now < next) {
              res[i] = cc;

              lefti = i - 1;
              while (lefti >= 0 && res[lefti] != res[i]) {
                --lefti;
              }
              righti = i + 1;
              while (righti < D && res[righti] != res[i]) {
                ++righti;
              }
            }
          }
      }
}

int main() {
  using std::endl;
  in.sync_with_stdio(false);
  out.sync_with_stdio(false);
  in.tie(nullptr);
  out.tie(nullptr);

  in >> D;
  for (size_t i = 0; i < 26; i++) {
    in >> C[i];
  }
  for (size_t d = 0; d < D; d++) {
    for (size_t i = 0; i < 26; i++) {
      in >> S[d][i];
    }
  }
  greedy1();
  // greedy2_init();
  // for (size_t i = 0; i < D; i+=26)
  //{
  //     greedy2(i,0);
  //     //greedy2(i+13,13);
  // }
  greedy3();

  for (size_t d = 0; d < D; d++) {
    out << res[d] + 1 << '\n';
  }
  // for (size_t d = 0; d < D; d++)
  //{
  //     out << (d%26) + 1 << '\n';
  // }

  return 0;
}
#endif


Fixed submission:
#if 1
#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <cstdint>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

template <typename T, typename U>
std::enable_if_t<std::rank<T>::value == 0> fill_all(T &arr, const U &v) {
  arr = v;
}
template <typename ARR, typename U>
std::enable_if_t<std::rank<ARR>::value != 0> fill_all(ARR &arr, const U &v) {
  for (auto &i : arr) {
    fill_all(i, v);
  }
}

auto &in = std::cin;
auto &out = std::cout;
#define all_range(C) std::begin(C), std::end(C)
const double PI =
    3.141592653589793238462643383279502884197169399375105820974944;

int32_t D;
int32_t C[30];
int32_t S[400][30];

int32_t res[400];
void greedy1() {
  int32_t last[40] = {};
  fill_all(last, -1);
  for (int32_t d = 0; d < D; d++) {
    int32_t max = S[d][0];
    int32_t max_index = 0;
    for (int32_t i = 0; i < 26; i++) {
      auto ss = S[d][i] + C[i] * (d - last[i]);
      if (max < ss) {
        max = ss;
        max_index = i;
      }
    }
    res[d] = max_index;
    last[max_index] = d;
  }
}

int numofbits5(uint32_t bits) {
  bits = (bits & 0x55555555) + (bits >> 1 & 0x55555555);
  bits = (bits & 0x33333333) + (bits >> 2 & 0x33333333);
  bits = (bits & 0x0f0f0f0f) + (bits >> 4 & 0x0f0f0f0f);
  bits = (bits & 0x00ff00ff) + (bits >> 8 & 0x00ff00ff);
  return (bits & 0x0000ffff) + (bits >> 16 & 0x0000ffff);
}

int32_t bittoindex[1 << 26];
void greedy2_init() {
  for (size_t i = 0; i < 26; i++) {
    bittoindex[1 << i] = i;
  }
}
inline int bittoindexf(int32_t bit) {
  switch (bit) {
#define bittoindexf_MACRO(i)                                                   \
  case (1 << i):                                                               \
    return i;

    bittoindexf_MACRO(0);
    bittoindexf_MACRO(1);
    bittoindexf_MACRO(2);
    bittoindexf_MACRO(3);
    bittoindexf_MACRO(4);
    bittoindexf_MACRO(5);
    bittoindexf_MACRO(6);
    bittoindexf_MACRO(7);
    bittoindexf_MACRO(8);
    bittoindexf_MACRO(9);
    bittoindexf_MACRO(10);
    bittoindexf_MACRO(11);
    bittoindexf_MACRO(12);
    bittoindexf_MACRO(13);
    bittoindexf_MACRO(14);
    bittoindexf_MACRO(15);
    bittoindexf_MACRO(16);
    bittoindexf_MACRO(17);
    bittoindexf_MACRO(18);
    bittoindexf_MACRO(19);
    bittoindexf_MACRO(20);
    bittoindexf_MACRO(21);
    bittoindexf_MACRO(22);
    bittoindexf_MACRO(23);
    bittoindexf_MACRO(24);
    bittoindexf_MACRO(25);
#undef bittoindexf_MACRO
  default:
    return 0;
  }
}
int32_t dp[1 << 27];
void greedy2(int start, int base) {
  constexpr int MAX_BIT = 26;
  constexpr int DIFFBASE = 0;
  auto CC = C + start;
  auto SS = S + start;

  fill_all(dp, 0);
  for (int32_t mask = 0; mask < (1 << MAX_BIT); mask++) {
    auto d = numofbits5(mask);
    auto tmp = ~mask;
    auto bit = tmp & -tmp;
    tmp ^= bit;
    while (bit < (1 << MAX_BIT)) {
      auto index = bittoindexf(bit);
      auto next = mask | bit;
      auto add = SS[d][index] +
                 CC[index] * (DIFFBASE + d) * (DIFFBASE + d) / 2 +
                 (26 + DIFFBASE - d) * (26 + DIFFBASE - d) / 2;
      dp[next] = std::max(dp[next], dp[mask] + add);

      bit = tmp & -tmp;
      tmp ^= bit;
    }
  }

  auto R = res + start;
  int32_t now = (1 << MAX_BIT) - 1;
  while (now > 0) {
    auto d = numofbits5(now) - 1;
    auto tmp = now;
    auto bit = tmp & -tmp;
    tmp ^= bit;
    while (bit < (1 << MAX_BIT)) {
      auto index = bittoindexf(bit);
      auto next = now ^ bit;
      auto add = SS[d][index] +
                 CC[index] * (DIFFBASE + d) * (DIFFBASE + d) / 2 +
                 (26 + DIFFBASE - d) * (26 + DIFFBASE - d) / 2;
      if (dp[now] == dp[next] + add) {
        R[d] = base + index;
        break;
      }

      bit = tmp & -tmp;
      tmp ^= bit;
    }

    now ^= bit;
  }
}
#include <chrono>
auto startTime = std::chrono::system_clock::now();
void greedy3() {
  while ((std::chrono::system_clock::now() - startTime) <
         std::chrono::milliseconds(1850))
    for (size_t COUNT = 0; COUNT < 125; COUNT++)
      for (int32_t i = 0; i < D; i++) {
        int lefti = i - 1;
        while (lefti >= 0 && res[lefti] != res[i]) {
          --lefti;
        }
        int righti = i + 1;
        while (righti < D && res[righti] != res[i]) {
          ++righti;
        }

        for (int32_t j = std::max(0, i - 26); j < D && j <= i + 26; j++) {
          if (i == j) {
            continue;
          }
          if (res[i] == res[j] && i < j) {
            break;
          }
          if (res[i] == res[j]) {
            continue;
          }

          int leftj = j - 1;
          while (leftj >= 0 && res[leftj] != res[j]) {
            --leftj;
          }
          int rightj = j + 1;
          while (rightj < D && res[rightj] != res[j]) {
            ++rightj;
          }

          if (std::max(lefti, leftj) <= std::min(i, j) &&
              std::max(i, j) <= std::min(righti, rightj)) {
            auto now =
                S[i][res[i]] - C[res[i]] * (i - lefti - 1) * (i - lefti) / 2 -
                (righti == D
                     ? 0
                     : C[res[i]] * (righti - i - 1) * (righti - i) / 2) +
                S[j][res[j]] - C[res[j]] * (j - leftj - 1) * (j - leftj) / 2 -
                (rightj == D ? 0
                             : C[res[j]] * (rightj - j - 1) * (rightj - j) / 2);
            auto next =
                S[j][res[i]] - C[res[i]] * (j - lefti - 1) * (j - lefti) / 2 -
                (righti == D
                     ? 0
                     : C[res[i]] * (righti - j - 1) * (righti - j) / 2) +
                S[i][res[j]] - C[res[j]] * (i - leftj - 1) * (i - leftj) / 2 -
                (rightj == D ? 0
                             : C[res[j]] * (rightj - i - 1) * (rightj - i) / 2);

            if (now < next) {
              std::swap(res[i], res[j]);

              lefti = i - 1;
              while (lefti >= 0 && res[lefti] != res[i]) {
                --lefti;
              }
              righti = i + 1;
              while (righti < D && res[righti] != res[i]) {
                ++righti;
              }
            }
          }
        }
        if (COUNT == 490)
          for (size_t cc = 0; i < 26; i++) {
            if (res[i] == cc) {
              continue;
            }

            int leftj = i - 1;
            while (leftj >= 0 && res[leftj] != cc) {
              --leftj;
            }
            int rightj = i + 1;
            while (rightj < D && res[rightj] != cc) {
              ++rightj;
            }

            auto now =
                S[i][res[i]] - C[res[i]] * (i - lefti - 1) * (i - lefti) / 2 -
                (righti == D
                     ? 0
                     : C[res[i]] * (righti - i - 1) * (righti - i) / 2) -
                (rightj == D
                     ? 0
                     : C[cc] * (rightj - leftj - 1) * (rightj - leftj) / 2);
            auto next =
                S[i][cc] - C[cc] * (i - leftj - 1) * (i - leftj) / 2 -
                (rightj == D ? 0
                             : C[cc] * (rightj - i - 1) * (rightj - i) / 2) -
                (righti == D
                     ? 0
                     : C[res[i]] * (righti - lefti - 1) * (righti - lefti) / 2);

            if (now < next) {
              res[i] = cc;

              lefti = i - 1;
              while (lefti >= 0 && res[lefti] != res[i]) {
                --lefti;
              }
              righti = i + 1;
              while (righti < D && res[righti] != res[i]) {
                ++righti;
              }
            }
          }
      }
}

int main() {
  using std::endl;
  in.sync_with_stdio(false);
  out.sync_with_stdio(false);
  in.tie(nullptr);
  out.tie(nullptr);

  in >> D;
  for (size_t i = 0; i < 26; i++) {
    in >> C[i];
  }
  for (size_t d = 0; d < D; d++) {
    for (size_t i = 0; i < 26; i++) {
      in >> S[d][i];
    }
  }
  greedy1();
  // greedy2_init();
  // for (size_t i = 0; i < D; i+=26)
  //{
  //     greedy2(i,0);
  //     //greedy2(i+13,13);
  // }
  greedy3();

  for (size_t d = 0; d < D; d++) {
    out << res[d] + 1 << '\n';
  }
  // for (size_t d = 0; d < D; d++)
  //{
  //     out << (d%26) + 1 << '\n';
  // }

  return 0;
}
#endif