結果
| 問題 |
No.1300 Sum of Inversions
|
| コンテスト | |
| ユーザー |
mumin
|
| 提出日時 | 2020-11-27 23:31:50 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 284 ms / 2,000 ms |
| コード長 | 5,710 bytes |
| コンパイル時間 | 1,963 ms |
| コンパイル使用メモリ | 182,188 KB |
| 実行使用メモリ | 20,224 KB |
| 最終ジャッジ日時 | 2024-09-13 01:10:56 |
| 合計ジャッジ時間 | 9,655 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 34 |
ソースコード
#include <bits/stdc++.h>
#define rep(i,n) for(int i = 0; i < (n); i++)
using namespace std;
using ll = long long;
using P = pair<int,int>;
const int mod = 998244353;
struct mint {
ll x; // typedef long long ll;
mint(ll x=0):x((x%mod+mod)%mod){}
mint operator-() const { return mint(-x);}
mint& operator+=(const mint a) {
if ((x += a.x) >= mod) x -= mod;
return *this;
}
mint& operator-=(const mint a) {
if ((x += mod-a.x) >= mod) x -= mod;
return *this;
}
mint& operator*=(const mint a) { (x *= a.x) %= mod; return *this;}
mint operator+(const mint a) const { return mint(*this) += a;}
mint operator-(const mint a) const { return mint(*this) -= a;}
mint operator*(const mint a) const { return mint(*this) *= a;}
mint pow(ll t) const {
if (!t) return 1;
mint a = pow(t>>1);
a *= a;
if (t&1) a *= *this;
return a;
}
// for prime mod
mint inv() const { return pow(mod-2);}
mint& operator/=(const mint a) { return *this *= a.inv();}
mint operator/(const mint a) const { return mint(*this) /= a;}
};
istream& operator>>(istream& is, const mint& a) { return is >> a.x;}
ostream& operator<<(ostream& os, const mint& a) { return os << a.x;}
int ceil_pow2(int n) {
int x = 0;
while ((1U << x) < (unsigned int)(n)) x++;
return x;
}
template <class S, S (*op)(S, S), S (*e)()> struct segtree {
public:
segtree() : segtree(0) {}
segtree(int n) : segtree(std::vector<S>(n, e())) {}
segtree(const std::vector<S>& v) : _n(int(v.size())) {
log = ceil_pow2(_n);
size = 1 << log;
d = std::vector<S>(2 * size, e());
for (int i = 0; i < _n; i++) d[size + i] = v[i];
for (int i = size - 1; i >= 1; i--) {
update(i);
}
}
void set(int p, S x) {
assert(0 <= p && p < _n);
p += size;
d[p] = x;
for (int i = 1; i <= log; i++) update(p >> i);
}
S get(int p) {
assert(0 <= p && p < _n);
return d[p + size];
}
S prod(int l, int r) {
assert(0 <= l && l <= r && r <= _n);
S sml = e(), smr = e();
l += size;
r += size;
while (l < r) {
if (l & 1) sml = op(sml, d[l++]);
if (r & 1) smr = op(d[--r], smr);
l >>= 1;
r >>= 1;
}
return op(sml, smr);
}
S all_prod() { return d[1]; }
template <bool (*f)(S)> int max_right(int l) {
return max_right(l, [](S x) { return f(x); });
}
template <class F> int max_right(int l, F f) {
assert(0 <= l && l <= _n);
assert(f(e()));
if (l == _n) return _n;
l += size;
S sm = e();
do {
while (l % 2 == 0) l >>= 1;
if (!f(op(sm, d[l]))) {
while (l < size) {
l = (2 * l);
if (f(op(sm, d[l]))) {
sm = op(sm, d[l]);
l++;
}
}
return l - size;
}
sm = op(sm, d[l]);
l++;
} while ((l & -l) != l);
return _n;
}
template <bool (*f)(S)> int min_left(int r) {
return min_left(r, [](S x) { return f(x); });
}
template <class F> int min_left(int r, F f) {
assert(0 <= r && r <= _n);
assert(f(e()));
if (r == 0) return 0;
r += size;
S sm = e();
do {
r--;
while (r > 1 && (r % 2)) r >>= 1;
if (!f(op(d[r], sm))) {
while (r < size) {
r = (2 * r + 1);
if (f(op(d[r], sm))) {
sm = op(d[r], sm);
r--;
}
}
return r + 1 - size;
}
sm = op(d[r], sm);
} while ((r & -r) != r);
return 0;
}
private:
int _n, size, log;
std::vector<S> d;
void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};
using S1 = mint;
S1 op1(S1 a, S1 b){
return a+b;
}
S1 e1(){
return 0;
}
using S2 = int;
S2 op2(S2 a, S2 b){
return a+b;
}
S2 e2(){
return 0;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<int> a(n), wa(n);
rep(i,n){
cin >> a[i];
wa[i] = a[i];
}
sort(wa.begin(), wa.end());
vector<int> va;
rep(i,n){
if(i == 0 || wa[i] != wa[i-1]) va.push_back(wa[i]);
}
vector<int> b(n);
rep(i,n){
b[i] = lower_bound(va.begin(), va.end(), a[i]) - va.begin();
}
segtree<S1, op1, e1> seg1(n), seg2(n);
segtree<S2, op2, e2> seg3(n), seg4(n);
rep(i,n){
int v = seg4.get(b[i]);
seg4.set(b[i], v+1);
mint t = seg2.get(b[i]);
t += a[i];
seg2.set(b[i], t);
}
mint ans = 0;
rep(i,n){
if(i > 0){
int id = b[i-1];
int v = seg3.get(id);
seg3.set(id, v+1);
mint t = seg1.get(id);
t += a[i-1];
seg1.set(id, t);
}
int id = b[i];
int v = seg4.get(id);
seg4.set(id, v-1);
mint t = seg2.get(id);
t -= a[i];
seg2.set(id, t);
mint tmp = a[i];
int n1 = seg4.prod(0, b[i]);
int n2 = seg3.prod(b[i]+1, n);
mint t1 = seg2.prod(0, b[i]);
mint t2 = seg1.prod(b[i]+1, n);
tmp *= n1;
tmp *= n2;
t1 *= n2;
t2 *= n1;
tmp += t1;
tmp += t2;
ans += tmp;
//cout << n1 << ' ' << n2 << ' ' << t1 << ' ' << t2 << ' ' << tmp << endl;
}
cout << ans << endl;
}
mumin