Rotated Inversions

这个绝对比 E 简单。

对于 ,是经典的逆序对板子,直接做。

然后考虑 增加 后如何更新答案。在所有数的相对关系中,只有最大的数变成了最小的,其他的都没有变化。因此,将最大的数删除掉,并作为最小的数重新插入回去即可。

线段树可以维护这个过程。使用 vectorvector 以数字大小为键记录其位置。使用线段树求逆序对的过程中,我们每插入一个数时会计数其后面有多少个比他小的数。删除过程类似,先将所有待删除数的标记取消,然后对与每个数,数一下它后面有多少个比它小的数,从答案中减掉就可以。

增加则是反过来,先数出每个数前有多少个比它大的,然后再把标记恢复。

#include <mrpython/typical_segment_tree.hpp>  // https://github.com/Mr-Python-in-China/mp-oi-library
#include <cstddef>
#include <iostream>
using namespace std;
istream& fin = cin;
ostream& fout = cout;
using ui = unsigned int;
using uli = unsigned long long int;
using li = long long int;
int main(void) {
  ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
  size_t n, m;
  fin >> n >> m;
  vector<vector<size_t>> d(m);
  for (size_t i = 0; i < n; ++i) {
    ui x;
    fin >> x;
    d[x].emplace_back(i);
  }
  uli v = 0;
  mrpython::typical_segment_tree_add<ui> tree(n, 0);
  auto get = [&](size_t l, size_t r) { return l == r ? 0 : tree.get(l, r); };
  for (size_t i = m - 1; i < m; --i) {
    for (size_t j : d[i]) v += get(0, j);
    for (size_t j : d[i]) tree.set(j, mrpython::const_function(1));
  }
  fout << v << '\n';
  for (size_t i = m - 1; i > 0; --i) {
    for (size_t j : d[i]) tree.set(j, mrpython::const_function(0));
    for (size_t j : d[i]) v -= get(j + 1, n);
    for (size_t j : d[i]) v += get(0, j);
    for (size_t j : d[i]) tree.set(j, mrpython::const_function(1));
    fout << v << '\n';
  }
  return 0;
}
posted @ 2025-03-13 18:33  MrPython  阅读(4)  评论(0)    收藏  举报  来源