// yukicoder: 121 傾向と対策:門松列(その2) // 2019.8.23 bal4u #include #include typedef long long ll; #if 1 #define gc() getchar_unlocked() #else #define gc() getchar() #endif int in() { // 非負整数の入力 int n = 0, c = gc(); do n = 10*n + (c & 0xf), c = gc(); while (c >= '0'); return n; } #define MAX 1000005 //// bit木 1-indexedに注意 int bitf[MAX], bits[MAX], bitn; void add(int *bit, int i) { while (i <= bitn) bit[i]++, i += i & -i; } void sub(int *bit, int i) { while (i <= bitn) bit[i]--, i += i & -i; } int sum(int *bit, int i) { int s = 0; while (i > 0) s += bit[i], i -= i & -i; return s; } //// 本問題関連 typedef struct { int a, id; } T; T t[MAX]; int N; int A[MAX]; int vf[MAX], vs[MAX]; int cmp(const void *u, const void *v) { return ((T *)u)->a - ((T *)v)->a; } void compact(int *a, int n) { // データ圧縮。圧縮後のデータ順序は圧縮前と同様 int i, v; for (i = 1; i <= n; i++) t[i].a = a[i], t[i].id = i; qsort(t+1, n, sizeof(T), cmp); v = 1; a[t[1].id] = v; for (i = 2; i <= n; i++) { if (t[i].a != t[i-1].a) v++; a[t[i].id] = v; } } int main() { int i, x, Q; ll same, ans; N = in(); for (i = 1; i <= N; i++) A[i] = in(); compact(A, N); // 1-indexed bitn = N+1; // bit木の初期化 // データをとりあえずすべて後半のbit木、頻度表に登録 for (i = 1; i <= N; i++) { add(bits, A[i]); // 後半のデータをbit木に追加 vs[A[i]]++; // 後半のデータを頻度表にも追加 } ans = 0; same = 0; // 前後半における同じ値のデータの累積和 // 最初のデータを個別に処理(門松列にならない) x = A[1], add(bitf, x), sub(bits, x); vf[x]++, vs[x]--, same += vs[x]; // 2個目~N-1までのデータについて処理していく for (i = 2; i < N; i++) { x = A[i]; // 処理対象であるデータ sub(bits, x), vs[x]--, same -= vf[x]; // A[i]を後半bit木や頻度表から取り出す int sf = sum(bitf, x-1), ss = sum(bits, x-1); // それよりも値の小さいデータの数を // A[i]を中心として、前後のデータの値で門松列になるペア数の算出 ans += (ll)sf*ss // A[i]よりも値の小さいデータペア数 + (ll)(i-1-sf-vf[x])*(N-i-ss-vs[x]) // A[i]よりも値の大きいデータペア数 - (same-(ll)vf[x]*vs[x]); // 前半と後半で、値が等しいデータペア数, A[i]と同じ値の数 add(bitf, x), same += vs[x], vf[x]++; // A[i]を前半のbit木と頻度表に登録 } printf("%lld\n", ans); return 0; }