結果
| 問題 |
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()