結果
問題 | No.121 傾向と対策:門松列(その2) |
ユーザー | bal4u |
提出日時 | 2019-08-23 18:55:42 |
言語 | C (gcc 12.3.0) |
結果 |
AC
|
実行時間 | 420 ms / 5,000 ms |
コード長 | 2,606 bytes |
コンパイル時間 | 1,966 ms |
コンパイル使用メモリ | 31,488 KB |
実行使用メモリ | 29,092 KB |
最終ジャッジ日時 | 2024-10-13 14:46:47 |
合計ジャッジ時間 | 4,412 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 11 ms
5,248 KB |
testcase_01 | AC | 17 ms
5,248 KB |
testcase_02 | AC | 2 ms
5,248 KB |
testcase_03 | AC | 175 ms
17,152 KB |
testcase_04 | AC | 420 ms
29,092 KB |
testcase_05 | AC | 187 ms
20,224 KB |
testcase_06 | AC | 246 ms
19,200 KB |
testcase_07 | AC | 277 ms
20,736 KB |
testcase_08 | AC | 225 ms
21,120 KB |
コンパイルメッセージ
main.c: In function 'in': main.c:10:14: warning: implicit declaration of function 'getchar_unlocked' [-Wimplicit-function-declaration] 10 | #define gc() getchar_unlocked() | ^~~~~~~~~~~~~~~~ main.c:16:24: note: in expansion of macro 'gc' 16 | int n = 0, c = gc(); | ^~
ソースコード
// yukicoder: 121 傾向と対策:門松列(その2) // 2019.8.23 bal4u #include <stdio.h> #include <stdlib.h> 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; }