Problem p02618 (C++) — buggy submission, verdict: 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;
  }
}

void greedy3() {
  for (int32_t i = 0; i < D; i++)
    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 lefti = i - 1;
      while (lefti >= 0 && res[lefti] != res[i]) {
        --lefti;
      }
      int righti = i + 1;
      while (righti < D && res[righti] != res[i]) {
        ++righti;
      }

      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]);
        }
      }
    }
}

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


Error: TLE

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;
  }
}

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);
  }

  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