[USACO23FEB] Equal Sum Subarrays G

我来教大家如何打暴力。

首先,根据题面,假设我们当前要修改第 个数。如果两个区间都包含 ,此时无论做何修改差都不变,都不包含同理。因此,我们找的两个区间应为:其中一个包含第 项,而另一个不含。

由于 非常小,我想到将所有符合条件的区间和都存下来,这个过程预处理出来或者套个前缀和都可以。之后,就是在两个数组中找绝对值差最小。排个序然后双指针搞一下就可以。

使用 std::sort 的时间复杂度为 ,还是很难通过。我经过简单的卡常拿到了 3.07s 的好成绩。于是我一怒之下换成基数排序就过了。

#include <bits/extc++.h>
using namespace std;
namespace pbds = __gnu_pbds;
istream& fin = cin;
ostream& fout = cout;
using ui = unsigned int;
using uli = unsigned long long int;
using li = long long int;
template <typename T> class PrefixSum {
  vector<T> sum;

 public:
  template <typename InputIterator, typename = _RequireInputIter<InputIterator>>
  PrefixSum(InputIterator begin, size_t n): sum(n + 1) {
    typename vector<T>::iterator it = next(sum.begin());
    *(it++) = *begin;
    for (size_t i = 1; i < n; ++i, ++it) *it = *prev(it) + *++begin;
  }
  T get_sum(size_t m, size_t n) { return sum[n] - sum[m]; }
  T get_val(size_t m) { return get_sum(m, m + 1); }
  T operator[](size_t m) { return get_val(m); }
  size_t size(void) { return sum.size(); }
};
// 我的基数排序模板仅支持无符号整数,因此有全部加一个偏移量到正数
template <typename ForwardIterator,
          typename = is_unsigned<typename ForwardIterator::value_type>>
void radixSort(ForwardIterator first, ForwardIterator last) {
  constexpr ui P = 8;
  constexpr size_t T =
      numeric_limits<typename ForwardIterator::value_type>::digits / P;
  size_t n = distance(first, last);
  ui W = 0;
  auto* dat = new typename ForwardIterator::value_type[n];
  for (size_t i = 0; i < T; ++i, W += P) {
    array<size_t, 1u << P> cnt{};
    for_each(first, last, [&](typename ForwardIterator::reference const x) {
      ++cnt[(x >> W) & ((1u << P) - 1)];
    });
    partial_sum(cnt.begin(), cnt.end(), cnt.begin());
    rotate(cnt.begin(), prev(cnt.end()), cnt.end()), cnt[0] = 0;
    for_each(first, last, [&](typename ForwardIterator::reference const x) {
      dat[cnt[(x >> W) & ((1u << P) - 1)]++] = x;
    });
    copy(dat, dat + n, first);
  }
  delete[] dat;
}
int main(void) {
  ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
  size_t n;
  fin >> n;
  vector<li> a(n);
  for (li& i : a) fin >> i;
  PrefixSum<li> p(a.begin(), n);
  for (size_t i = 0; i < n; ++i) {
    vector<uli> s, t;
    for (size_t j = 0; j < i; ++j)
      for (size_t k = j; k < i; ++k)
        s.emplace_back((uli)p.get_sum(j, k + 1) - numeric_limits<li>::min());
    for (size_t j = i + 1; j < n; ++j)
      for (size_t k = j; k < n; ++k)
        s.emplace_back((uli)p.get_sum(j, k + 1) - numeric_limits<li>::min());
    uli ans = numeric_limits<uli>::max();
    for (size_t j = 0; j <= i; ++j)
      for (size_t k = i; k < n; ++k)
        t.emplace_back((uli)p.get_sum(j, k + 1) - numeric_limits<li>::min());
    radixSort(s.begin(), s.end()), radixSort(t.begin(), t.end());
    vector<uli>::iterator it = s.begin();
    for (uli i : t) {
      while (it != s.end() && *it < i) ++it;
      if (it != s.end()) ans = min(ans, *it - i);
      if (it != s.begin()) ans = min(ans, i - *prev(it));
    }
    fout << ans << '\n';
  }
  return 0;
}
posted @ 2024-09-25 21:35  MrPython  阅读(3)  评论(0)    收藏  举报  来源