結果
| 問題 |
No.2616 中央番目の中央値
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2024-01-30 11:58:22 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 96 ms / 2,000 ms |
| コード長 | 5,650 bytes |
| コンパイル時間 | 2,523 ms |
| コンパイル使用メモリ | 216,488 KB |
| 最終ジャッジ日時 | 2025-02-19 00:46:35 |
|
ジャッジサーバーID (参考情報) |
judge3 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 37 |
ソースコード
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) { return (ull)rng() % B; }
// 0-indexed
template <typename T> struct BIT {
int n;
vector<T> bit, ary;
BIT(int n = 0) : n(n), bit(n + 1), ary(n) {}
T operator[](int k) { return ary[k]; }
// [0, i)
T sum(int i) {
T res = 0;
for (; i > 0; i -= (i & -i)) {
res += bit[i];
}
return res;
}
// [l, r)
T sum(int l, int r) { return sum(r) - sum(l); }
void add(int i, T a) {
ary[i] += a;
i++;
for (; i <= n; i += (i & -i)) {
bit[i] += a;
}
}
int lower_bound(T k) { // k <= sum(res)
if (k <= 0) return 0;
int res = 0, i = 1;
while ((i << 1) <= n)
i <<= 1;
for (; i; i >>= 1) {
if (res + i <= n and bit[res + i] < k) {
k -= bit[res += i];
}
}
return res;
}
// The 2nd UC Stage 9: Qinhuangdao - I
// 円環状で見たときに bit[i]+bit[i-1]+...+bit[j] を求める
T sum_cyc(int i, int j) {
if (j <= i) return sum(j, i + 1);
else return sum(0, i + 1) + sum(j, n);
}
// The 2nd UC Stage 9: Qinhuangdao - I
// 円環状で見たときに bit[i]+bit[i-1]+...+bit[j] >= k となる最近の j と左辺の総和を求める
// 雑にlog2つ
pair<int, T> lower_bound_cyc(int j, T k) {
T prefix = sum(j + 1);
if (prefix < k) {
k -= prefix;
int l = 0, r = n;
while (r - l > 1) {
int mid = (l + r) / 2;
T s = sum(mid, n);
if (s >= k) {
l = mid;
} else {
r = mid;
}
}
return {l, prefix + sum(l, n)};
} else {
int l = 0, r = j + 1;
while (r - l > 1) {
int mid = (l + r) / 2;
T s = sum(mid, j + 1);
if (s >= k) {
l = mid;
} else {
r = mid;
}
}
return {l, sum(l, j + 1)};
}
}
};
template <int mod> struct static_modint {
using mint = static_modint;
int x;
static_modint() : x(0) {}
static_modint(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
mint &operator+=(const mint &rhs) {
if ((x += rhs.x) >= mod) x -= mod;
return *this;
}
mint &operator-=(const mint &rhs) {
if ((x += mod - rhs.x) >= mod) x -= mod;
return *this;
}
mint &operator*=(const mint &rhs) {
x = (int)(1LL * x * rhs.x % mod);
return *this;
}
mint &operator/=(const mint &rhs) { return *this = *this * rhs.inv(); }
mint pow(long long n) const {
mint _x = *this, r = 1;
while (n) {
if (n & 1) r *= _x;
_x *= _x;
n >>= 1;
}
return r;
}
mint inv() const { return pow(mod - 2); }
mint operator+() const { return *this; }
mint operator-() const { return mint() - *this; }
friend mint operator+(const mint &lhs, const mint &rhs) { return mint(lhs) += rhs; }
friend mint operator-(const mint &lhs, const mint &rhs) { return mint(lhs) -= rhs; }
friend mint operator*(const mint &lhs, const mint &rhs) { return mint(lhs) *= rhs; }
friend mint operator/(const mint &lhs, const mint &rhs) { return mint(lhs) /= rhs; }
friend bool operator==(const mint &lhs, const mint &rhs) { return lhs.x == rhs.x; }
friend bool operator!=(const mint &lhs, const mint &rhs) { return lhs.x != rhs.x; }
friend ostream &operator<<(ostream &os, const mint &p) { return os << p.x; }
friend istream &operator>>(istream &is, mint &a) {
int64_t t;
is >> t;
a = static_modint<mod>(t);
return (is);
}
};
const unsigned int mod = 998244353;
using modint = static_modint<mod>;
modint mod_pow(ll n, ll x) { return modint(n).pow(x); }
modint mod_pow(modint n, ll x) { return n.pow(x); }
template <typename T> struct Comination {
vector<T> p, invp;
Comination(int sz) : p(sz + 1), invp(sz + 1) {
p[0] = 1;
for (int i = 1; i <= sz; ++i) {
p[i] = p[i - 1] * i;
}
invp[sz] = p[sz].inv();
for (int i = sz - 1; i >= 0; --i) {
invp[i] = invp[i + 1] * (i + 1);
}
}
T comb(int n, int r) {
if (r < 0 or n < r) return 0;
return p[n] * invp[n - r] * invp[r];
}
T big_comb(T n, int r) {
T res = invp[r];
for (int i = 0; i < r; ++i) {
res *= (n - i);
}
return res;
}
};
using Comb = Comination<modint>;
Comb P(1 << 20);
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<int> p(n);
for (int i = 0; i < n; i++) {
cin >> p[i];
p[i] -= 1;
}
BIT<int> bit1(n), bit2(n);
for (int i = 0; i < n; i++) {
bit2.add(i, 1);
}
vector<int> a(n), b(n), c(n), d(n);
for (int i = 0; i < n; i++) {
bit2.add(p[i], -1);
a[i] = bit1.sum(p[i]);
b[i] = bit2.sum(p[i]);
c[i] = i - a[i];
d[i] = (n - 1 - i) - b[i];
bit1.add(p[i], 1);
}
modint res = 0;
for (int i = 0; i < n; i++) {
res += P.comb(a[i] + d[i], a[i]) * P.comb(b[i] + c[i], b[i]);
}
cout << res << endl;
}