問題
長さ $3^K$ のフラクタル数列に対し、更新クエリとフラクタル制約付き LIS クエリ(区間 $[l, r)$、$l, r$ はレベル境界)を処理せよ。
制約
$1 \le K \le 6$($N \le 729$)
$1 \le Q \le 10^5$
$0 \le V_i \le 10^9$
入出力例
入力例 1
2 3
1 3 2 4 5 1 2 6 3
2 0 9
1 3 7
2 0 9出力例 1
5
6ヒント (段階的開示)
ヒント1: 方向性
フラクタル構造の自己相似性を分割統治で活用。
ヒント2: アプローチ
各ブロックで patience sorting テールを管理、ブロック間で出口値を引き継ぐ。
ヒント3: 直接計算
$K \le 6$, $N \le 729$ なので各クエリ $O(N \log N)$ で十分。
模範解答 (Python)
import sys
from bisect import bisect_left
def main():
input_data = sys.stdin.read().split()
idx = 0
def rd():
nonlocal idx
v = input_data[idx]; idx += 1
return v
K = int(rd()); Q = int(rd())
V = [int(rd()) for _ in range(3**K)]
N = 3**K
def fractal_lis_range(l, r):
if r - l == 1:
return 1
tails = []
def process(bl, br):
if br - bl == 1:
v = V[bl]
pos = bisect_left(tails, v)
if pos == len(tails):
tails.append(v)
else:
tails[pos] = v
return
bs = (br - bl) // 3
for i in range(3):
process(bl + i * bs, bl + (i + 1) * bs)
process(l, r)
return len(tails)
for _ in range(Q):
t = int(rd())
if t == 1:
p = int(rd()); x = int(rd())
V[p] = x
else:
l = int(rd()); r = int(rd())
print(fractal_lis_range(l, r))
main()
Step-by-Step 解説
1フラクタル構造
レベル $k$ ブロック = レベル $k-1$ × 3。ブロック内・ブロック間共に単調増加制約。
レベル $k$ ブロック = レベル $k-1$ × 3。ブロック内・ブロック間共に単調増加制約。
2通常 LIS との違い
制約により patience sorting 適用方法が異なる。
制約により patience sorting 適用方法が異なる。
3分割統治
各クエリで再帰的に小ブロック処理 → tails に追加。
各クエリで再帰的に小ブロック処理 → tails に追加。
4更新
点更新は直接 $V[p]$ を書き換え。
点更新は直接 $V[p]$ を書き換え。
よくあるミス
| ミス | 原因 | 正しい書き方 |
|---|---|---|
| フラクタル制約無視 | 通常 LIS で解く | 再帰的ブロック構造を保持 |
| K=0 の境界 | 再帰の基底 | 葉では return 1 |
| bisect_left vs right | 等値の扱い | 狭義単調増加なら bisect_left |
次のステップ
- 区間更新 + 遅延セグメント木