結果
| 問題 |
No.2161 Black Market
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2022-12-12 00:27:09 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 5,674 ms / 7,000 ms |
| コード長 | 5,378 bytes |
| コンパイル時間 | 184 ms |
| コンパイル使用メモリ | 82,432 KB |
| 実行使用メモリ | 183,564 KB |
| 最終ジャッジ日時 | 2024-10-15 19:30:50 |
| 合計ジャッジ時間 | 35,670 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 37 |
ソースコード
from bisect import bisect_left
class SegTree:
def __init__(self, n, e, ope, lst=[]):
self.N0 = 2 ** (n - 1).bit_length()
self.e = e
self.ope = ope
self.data = [e] * (2 * self.N0)
if lst:
for i in range(n):
self.data[self.N0 + i] = lst[i]
for i in range(self.N0 - 1, 0, -1):
self.data[i] = self.ope(self.data[2 * i], self.data[2 * i + 1])
def build(self):
for i in range(self.N0 - 1, 0, -1):
self.data[i] = self.ope(self.data[2 * i], self.data[2 * i + 1])
def update(self, i, x): #a_iの値をxに更新
i += self.N0
self.data[i] = x
while i > 1:
i >>= 1
self.data[i] = self.ope(self.data[2 * i], self.data[2 * i + 1])
def add(self, i, x):
self.update(i, x + self.get(i))
def set(self, i, x):
self.data[self.N0 + i] = x
def query(self, l, r): #区間[l, r)での演算結果
if r <= l:
return self.e
lres = self.e
rres = self.e
l += self.N0
r += self.N0
while l < r:
if l & 1:
lres = self.ope(lres, self.data[l])
l += 1
if r & 1:
r -= 1
rres = self.ope(self.data[r], rres)
l >>= 1
r >>= 1
return self.ope(lres, rres)
def get(self, i): #a_iの値を返す
return self.data[self.N0 + i]
class RangeTree:
def __init__(self, e, ope, inflog=32):
self.e = e
self.ope = ope
self.ps = []
self.inflog = inflog
self.inf = 1 << self.inflog
self.mask = (self.inf) - 1
def add_point(self, x, y):
self.ps.append((x << self.inflog) | y)
def _merge(self, A, B):
ret = []
al = len(A)
bl = len(B)
ap = 0
bp = 0
while ap < al and bp < bl:
if A[ap] < B[bp]:
ret.append(A[ap])
ap += 1
elif A[ap] == B[bp]:
ret.append(A[ap])
ap += 1
bp += 1
else:
ret.append(B[bp])
bp += 1
if ap == al:
ret += B[bp:]
else:
ret += A[ap:]
return ret
def build(self):
self.ps = sorted(set(self.ps))
self.n = len(self.ps)
self.ys = [[] for _ in range(2 * self.n)]
for i in range(self.n):
self.ys[i + self.n].append(self.ps[i] & self.mask)
for i in range(self.n - 1, -1, -1):
self.ys[i] = self._merge(self.ys[i << 1], self.ys[(i << 1) | 1])
self.le = [0] * (2 * self.n + 1)
for i in range(1, 2 * self.n + 1):
self.le[i] = self.le[i - 1] + len(self.ys[i - 1])
self.seg = SegTree(self.le[-1], self.e, self.ope)
def _idx(self, x):
return bisect_left(self.ps, x << self.inflog)
def _idy(self, i, y):
return bisect_left(self.ys[i], y) + self.le[i]
def add(self, x, y, w):
i = bisect_left(self.ps, (x << self.inflog) | y)
i += self.n
while i > 0:
self.seg.add(self._idy(i, y), w)
i >>= 1
def add_init(self, xyw):
plus = [0] * (self.le[-1])
for x, y, w in xyw:
i = bisect_left(self.ps, (x << self.inflog) | y)
i += self.n
while i > 0:
plus[self._idy(i, y)] += w
i >>= 1
for i, p in enumerate(plus):
if p != 0:
self.seg.add(i, p)
def query(self, l, d, r, u):
L = self.e
R = self.e
a = self._idx(l) + self.n
b = self._idx(r) + self.n
while a < b:
if a & 1:
L = self.ope(L, self.seg.query(self._idy(a, d), self._idy(a, u)))
a += 1
if b & 1:
b -= 1
R = self.ope(self.seg.query(self._idy(b, d), self._idy(b, u)), R)
a >>= 1
b >>= 1
return self.ope(L, R)
n, k, l, p = map(int, input().split())
ab = [list(map(int, input().split())) for _ in range(n)]
ll = min(20, n)
bef = ab[:ll]
aft = ab[ll:]
def f(A):
n = len(A)
lst = [[] for _ in range(n + 1)]
lst[0].append((0, 0))
for i, (a, b) in enumerate(A):
for j in range(i, -1, -1):
for c, d in lst[j]:
lst[j + 1].append((a + c, b + d))
return lst
bef = f(bef)
if not aft:
ans = 0
for i in range(min(k + 1, len(bef))):
for a, b in bef[i]:
if a <= l and b >= p:
ans += 1
print(ans)
exit()
aft = f(aft)
le = len(aft)
rt = [RangeTree(0, lambda x, y: x + y) for _ in range(le)]
for i in range(le):
abc = []
for j in range(i + 1):
for a, b in aft[j]:
if a > l:
continue
b = min(b, p)
rt[i].add_point(a, b)
abc.append((a, b, 1))
rt[i].build()
rt[i].add_init(abc)
ans = 0
for i in range(len(bef)):
if i > k:
break
j = min(k - i, le - 1)
for a, b in bef[i]:
if a > l:
continue
aa = l - a + 1
bb = max(0, p - b)
ans += rt[j].query(0, bb, aa, 1 << 30)
print(ans)