結果
問題 |
No.2873 Kendall's Tau
|
ユーザー |
|
提出日時 | 2025-03-01 03:32:25 |
言語 | PyPy3 (7.3.15) |
結果 |
TLE
|
実行時間 | - |
コード長 | 4,785 bytes |
コンパイル時間 | 623 ms |
コンパイル使用メモリ | 82,400 KB |
実行使用メモリ | 54,388 KB |
最終ジャッジ日時 | 2025-03-01 03:32:35 |
合計ジャッジ時間 | 8,606 ms |
ジャッジサーバーID (参考情報) |
judge6 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 4 TLE * 1 -- * 25 |
ソースコード
## https://yukicoder.me/problems/no/2873 import math class SegmentTree: """ 非再帰版セグメント木。 更新は「加法」、取得は「最大値」のもの限定。 """ def __init__(self, init_array): n = 1 while n < len(init_array): n *= 2 self.size = n self.array = [[] for _ in range(2 * self.size)] for i, a in enumerate(init_array): self.array[self.size + i] = a end_index = self.size start_index = end_index // 2 while start_index >= 1: for i in range(start_index, end_index): self._op(self.array[i], self.array[2 * i], self.array[2 * i + 1]) end_index = start_index start_index = end_index // 2 def _op(self, array, left, right): array.clear() l_index = 0 r_index = 0 while l_index < len(left) or r_index < len(right): if l_index == len(left): array.append(right[r_index]) r_index += 1 elif r_index == len(right): array.append(left[l_index]) l_index += 1 else: if left[l_index] <= right[r_index]: array.append(left[l_index]) l_index += 1 else: array.append(right[r_index]) r_index += 1 def add(self, x, a): index = self.size + x self.array[index].append(a) while index > 1: index //= 2 self._op(self.array[index], self.array[2 * index], self.array[2 * index + 1]) def get_positive(self, l, r, y): L = self.size + l; R = self.size + r # 2. 区間[l, r)の最大値を求める s = 0 while L < R: if R & 1: R -= 1 s += self.positive(self.array[R], y) if L & 1: s += self.positive(self.array[L], y) L += 1 L >>= 1; R >>= 1 return s def get_negative(self, l, r, y): L = self.size + l; R = self.size + r # 2. 区間[l, r)の最大値を求める s = 0 while L < R: if R & 1: R -= 1 s += self.negative(self.array[R], y) if L & 1: s += self.negative(self.array[L], y) L += 1 L >>= 1; R >>= 1 return s def positive(self, array, y): if len(array) == 0: return 0 if array[-1] <= y: return 0 low = 0 high = len(array) - 1 while high - low > 1: mid = (high + low) // 2 if array[mid] > y: high = mid else: low = mid if array[low] > y: return len(array) - low else: return len(array) - high def negative(self, array, y): if len(array) == 0: return 0 if array[0] >= y: return 0 low = 0 high = len(array) - 1 while high - low > 1: mid = (high + low) // 2 if array[mid] < y: low = mid else: high = mid if array[high] < y: return high + 1 else: return low + 1 def main(): N = int(input()) xy = [] for _ in range(N): x, y = map(int, input().split()) xy.append((x, y)) # R, Sの計算 R = 0 S = 0 x_map = {} y_map = {} tot = 0 for x, y in xy: if x in x_map: R += tot - x_map[x] else: R += tot if y in y_map: S += tot - y_map[y] else: S += tot if x not in x_map: x_map[x] = 0 x_map[x] += 1 if y not in y_map: y_map[y] = 0 y_map[y] += 1 tot += 1 # P,Qの計算 ## xについての座標圧縮 x_set = set() for x, _ in xy: x_set.add(x) x_list = list(x_set) x_list.sort() x_map = {} for i, x in enumerate(x_list): x_map[x] = i x_max = len(x_list) seg_tree = SegmentTree([[] for _ in range(x_max + 1)]) P = 0 Q = 0 for x, y in xy: x_ = x_map[x] p1 = seg_tree.get_negative(0, x_, y) p2 = seg_tree.get_positive(x_ + 1, seg_tree.size, y) P += p1 + p2 q1 = seg_tree.get_positive(0, x_, y) q2 = seg_tree.get_negative(x_ + 1, seg_tree.size, y) Q += q1 + q2 seg_tree.add(x_, y) answer = (P - Q) / math.sqrt(R * S) print(answer) if __name__ == "__main__": main()