結果
問題 | No.1720 Division Permutation |
ユーザー |
|
提出日時 | 2021-10-17 15:17:13 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 1,505 ms / 4,000 ms |
コード長 | 15,874 bytes |
コンパイル時間 | 151 ms |
コンパイル使用メモリ | 82,260 KB |
実行使用メモリ | 238,088 KB |
最終ジャッジ日時 | 2024-09-23 03:56:00 |
合計ジャッジ時間 | 52,449 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 60 |
ソースコード
from typing import List, Tupleclass lazy_segtree:"""It is the data structure for the pair of a monoid (S, op) and a set F of S to S mappings that satisfies the following properties.> F contains the identity map id, where the identity map is the map that satisfies id(x) = x for all x in S.> F is closed under composition, i.e., `composition(f, g)` is in F for all `f`, `g` in F.> `f(op(x, y)) = op(f(x), f(y))` holds for all `f` in F and `x`, `y` in S.Given an array of length n, it processes the following queries in O(log n) time(see Appendix in the document of AC Library for further details).> Acting the map f in F (cf. x = f(x)) on all the elements of an interval> Calculating the product of the elements of an intervalFor simplicity, in this document, we assume that the oracles `op`, `e`, `mapping`, `composition`, and `id_` work in constant time.If these oracles work in O(T) time, each time complexity appear in this document is multipled by O(T)."""__slots__ = ["op", "e", "mapping", "composition","id_", "n", "log", "size", "d", "lz"]def __init__(self, n_or_list, op, e, mapping, composition, id_):"""The following should be defined.> The binary operation `op(a, b)`> The function `e()` that returns the identity element> The function `mapping(f, x)` that returns f(x)> The function `composition(f, g)` that returns f composed with g> The function `id_()` that returns the identity mapFor example, for Range Multiplication Range Sum Query, the definitions are as follows.```pythonseg = lazy_segtree(10, lambda a, b: a+b, lambda: 0, lambda f, x: f*x, lambda f, g: f*g, lambda: 1)```> If `n_or_list` is an integer, it creates an array `a` of length `n_or_list`. All the elements are initialized to `e()`.> If `n_or_list` is a list, it creates an array `a` of length `len(n_or_list)`, initialized to `n_or_list`.> Otherwise, it raises `TypeError`.Constraints-----------> 0 <= n <= 10 ** 8Complexity----------> O(n)"""self.op = opself.e = eself.mapping = mappingself.composition = compositionself.id_ = id_if isinstance(n_or_list, int):self.n = n_or_listself.log = (self.n - 1).bit_length()self.size = 1 << self.logself.d = [self.e() for _ in range(self.size * 2)]self.lz = [self.id_() for _ in range(self.size)]elif isinstance(n_or_list, list):self.n = len(n_or_list)self.log = (self.n - 1).bit_length()self.size = 1 << self.logself.d = [self.e() for _ in range(self.size)] + n_or_list + \[self.e() for _ in range(self.size - self.n)]for i in range(self.size - 1, 0, -1):self.d[i] = self.op(self.d[2*i], self.d[2*i+1])self.lz = [self.id_() for _ in range(self.size)]else:raise TypeError(f"The argument 'n_or_list' must be an integer or a list, not {type(n_or_list).__name__}")def set(self, p, x):"""It assigns x to `a[p]`.Constraints-----------> 0 <= p < nComplexity----------> O(log n)"""# assert 0 <= p < self.np += self.sizefor i in range(self.log, 0, -1):self._push(p >> i)self.d[p] = xfor i in range(1, self.log + 1):self._update(p >> i)def get(self, p):"""It returns `a[p]`.Constraints-----------> 0 <= p < nComplexity----------> O(log n)"""# assert 0 <= p < self.np += self.sizefor i in range(self.log, 0, -1):self._push(p >> i)return self.d[p]def prod(self, l, r):"""It returns `op(a[l], ..., a[r - 1])`, assuming the properties of the monoid.It returns `e()` if l = r.Constraints-----------> 0 <= l <= r <= nComplexity----------> O(log n)"""# assert 0 <= l <= r <= self.nif l == r:return self.e()l += self.sizer += self.sizeindices = []l0 = (l // (l & -l)) // 2r0 = (r // (r & -r) - 1) // 2while l0 != r0:if l0 < r0:indices.append(r0)r0 //= 2else:indices.append(l0)l0 //= 2while r0:indices.append(r0)r0 //= 2for index in reversed(indices):self._push(index)sml = self.e()smr = self.e()while l < r:if l % 2:sml = self.op(sml, self.d[l])l += 1if r % 2:r -= 1smr = self.op(self.d[r], smr)l //= 2r //= 2return self.op(sml, smr)def all_prod(self):"""It returns `op(a[0], ..., a[n - 1])`, assuming the properties of the monoid.It returns `e()` if n = 0.Complexity----------> O(1)"""return self.d[1]def point_apply(self, p, f):"""It applies `a[p] = f(a[p])`.Constraints-----------> 0 <= p < nComplexity----------> O(log n)"""# assert 0 <= p <= self.np += self.sizefor i in range(self.log, 0, -1):self._push(p >> i)self.d[p] = self.mapping(f, self.d[p])for i in range(1, self.log + 1):self._update(p >> i)def apply(self, l, r, f):"""It applies `a[i] = f(a[i])` for all `i` with `l <= i < r`.Constraints-----------> 0 <= l <= r <= nComplexity----------> O(log n)"""# assert 0 <= l <= r <= self.nif l == r:returnl += self.sizer += self.sizeindices = []l0 = (l // (l & -l)) // 2r0 = (r // (r & -r) - 1) // 2while l0 != r0:if l0 < r0:indices.append(r0)r0 //= 2else:indices.append(l0)l0 //= 2while r0:indices.append(r0)r0 //= 2for index in reversed(indices):self._push(index)while l < r:if l % 2:self._all_apply(l, f)l += 1if r % 2:r -= 1self._all_apply(r, f)l //= 2r //= 2for index in indices:self._update(index)def max_right(self, l, g):"""It returns an index `r` that satisfies both of the following.> `r == l` or `g(op(a[l], a[l + 1], ..., a[r - 1])) == True`> `r == n` or `g(op(a[l], a[l + 1], ..., a[r])) == False`If `g` is monotone, this is the maximum `r` that satisfies `g(op(a[l], a[l + 1], ..., a[r - 1])) == True`.Constraints-----------> if `g` is called with the same argument, it returns the same value, i.e., `g` has no side effect.> `g(e()) == True`> 0 <= l <= nComplexity----------> O(log n)"""# assert 0 <= l <= self.n# assert g(self.e())if l == self.n:return self.nl += self.sizefor i in range(self.log, 0, -1):self._push(l >> i)sm = self.e()while True:while l % 2 == 0:l //= 2if not g(self.op(sm, self.d[l])):while l < self.size:self._push(l)l *= 2if g(self.op(sm, self.d[l])):sm = self.op(sm, self.d[l])l += 1return l - self.sizesm = self.op(sm, self.d[l])l += 1if l == l & -l:breakreturn self.ndef min_left(self, r, g):"""It returns an index `l` that satisfies both of the following.> `l == r` or `g(op(a[l], a[l + 1], ..., a[r - 1])) == True`> `l == 0` or `g(op(a[l - 1], a[l], ..., a[r - 1])) == False`If `g` is monotone, this is the minimum `l` that satisfies `g(op(a[l], a[l + 1], ..., a[r - 1])) == True`.Constraints-----------> if `g` is called with the same argument, it returns the same value, i.e., `g` has no side effect.> `g(e()) == True`> 0 <= r <= nComplexity----------> O(log n)"""# assert 0 <= r <= self.n# assert g(self.e())if r == 0:return 0r += self.sizefor i in range(self.log, 0, -1):self._push((r - 1) >> i)sm = self.e()while True:r -= 1while (r > 1 and r % 2):r //= 2if not g(self.op(self.d[r], sm)):while r < self.size:self._push(r)r = 2 * r + 1if g(self.op(self.d[r], sm)):sm = self.op(self.d[r], sm)r -= 1return r + 1 - self.sizesm = self.op(self.d[r], sm)if r == r & -r:breakreturn 0def _update(self, k):self.d[k] = self.op(self.d[2 * k], self.d[2 * k + 1])def _all_apply(self, k, f):self.d[k] = self.mapping(f, self.d[k])if k < self.size:self.lz[k] = self.composition(f, self.lz[k])def _push(self, k):self._all_apply(2 * k, self.lz[k])self._all_apply(2 * k + 1, self.lz[k])self.lz[k] = self.id_()class permutation_tree:def __init__(self, vec: List[int]) -> None:self.vec = vecself.build()def get_range(self, x: Tuple[int, int], y: Tuple[int, int]) -> Tuple[int, int]:return (min(x[0], y[0]), max(x[1], y[1]))def adj(self, i: int, j: int) -> bool:return self.range_[i][1] == self.range_[j][0]def length(self, i: int) -> int:return self.range_[i][1] - self.range_[i][0]def add_edge(self, p: int, c: int) -> None:self.parent[c] = pself.children[p].append(c)def build(self) -> None:max_stack = [-1]min_stack = [-1]nodes = []self.sz = n = len(self.vec)self.parent = [-1] * (n * 2)self.children = [[] for _ in range(n * 2)]self.range_ = [(0, 0)] * (n * 2)self.span = [(0, 0)] * (n * 2)self.typ = [0] * (n * 2)seg = lazy_segtree([0] * (n * 2), min, lambda: 1 << 30,lambda f, x: f + x, lambda f, g: f + g, lambda: 0)for i in range(n):while max_stack[-1] != -1 and self.vec[max_stack[-1]] < self.vec[i]:tmp = max_stack.pop()seg.apply(max_stack[-1] + 1, tmp + 1,self.vec[i] - self.vec[tmp])max_stack.append(i)while min_stack[-1] != -1 and self.vec[min_stack[-1]] > self.vec[i]:tmp = min_stack.pop()seg.apply(min_stack[-1] + 1, tmp + 1,self.vec[tmp] - self.vec[i])min_stack.append(i)self.range_[i] = (self.vec[i], self.vec[i] + 1)self.span[i] = (i, i + 1)cur = iwhile True:if nodes and (self.adj(nodes[-1], cur) or self.adj(cur, nodes[-1])):if (self.adj(nodes[-1], cur) and self.typ[nodes[-1]] == 2) or (self.adj(cur, nodes[-1]) and self.typ[nodes[-1]] == 1):self.add_edge(nodes[-1], cur)self.range_[nodes[-1]] = self.get_range(self.range_[nodes[-1]], self.range_[cur])self.span[nodes[-1]] = self.get_range(self.span[nodes[-1]], self.span[cur])cur = nodes.pop()else:self.add_edge(self.sz, nodes[-1])self.add_edge(self.sz, cur)self.typ[self.sz] = 2 if self.adj(nodes[-1], cur) else 1self.range_[self.sz] = self.get_range(self.range_[nodes[-1]], self.range_[cur])self.span[self.sz] = self.get_range(self.span[nodes[-1]], self.span[cur])cur = self.szself.sz += 1nodes.pop()elif i + 1 - self.length(cur) and seg.prod(0, i + 1 - self.length(cur)) == 0:len_ = self.length(cur)rng = self.range_[cur]sp = self.span[cur]self.add_edge(self.sz, cur)while True:len_ += self.length(nodes[-1])rng = self.get_range(rng, self.range_[nodes[-1]])sp = self.get_range(sp, self.span[nodes[-1]])self.add_edge(self.sz, nodes[-1])nodes.pop()if rng[1] - rng[0] == len_:breakself.children[self.sz].reverse()self.range_[self.sz] = rngself.span[self.sz] = spcur = self.szself.sz += 1else:breaknodes.append(cur)seg.apply(0, i + 1, -1)self.shrink()def shrink(self) -> None:self.parent = self.parent[:self.sz]self.children = self.children[:self.sz]self.range_ = self.range_[:self.sz]self.span = self.span[:self.sz]self.typ = self.typ[:self.sz]MOD = 998244353N, K = map(int, input().split())Ps = list(map(int, input().split()))def add(f, g):if len(f) < len(g):f, g = g, fans = f.copy()for i, gi in enumerate(g):ans[i] += gians[i] %= MODreturn ans[:K+1]def multiply(f, g):ans = [0] * (len(f) + len(g) - 1)for i, fi in enumerate(f):for j, gj in enumerate(g):ans[i + j] += fi * gjans[i + j] %= MODreturn ans[:K+1]perm_tree = permutation_tree(Ps)dp = [[] for _ in range(perm_tree.sz)]root = perm_tree.parent.index(-1)# print(root)stack = [~root, root]while stack:i = stack.pop()if i >= 0:for ni in perm_tree.children[i]:stack.append(~ni)stack.append(ni)else:i = ~iif 0 <= i < N:dp[i] = [0, 1]continuet = perm_tree.typ[i]cs = perm_tree.children[i]if t:csum = [[1]]ans = [1]for j, c in enumerate(cs):ans = multiply(ans, dp[c])if j >= 1:ans = add(ans, [0] + csum[j-1])csum.append(add(csum[-1], ans))dp[i] = anselse:t = [1]for c in cs:t = multiply(t, dp[c])t = add(t, [0, 1])dp[i] = tans = dp[root]while len(ans) < K + 1:ans.append(0)print(*ans[1:], sep='\n')