結果
問題 | No.878 Range High-Element Query |
ユーザー | 👑 seekworser |
提出日時 | 2024-06-17 21:59:20 |
言語 | Nim (2.0.2) |
結果 |
AC
|
実行時間 | 151 ms / 2,000 ms |
コード長 | 5,251 bytes |
コンパイル時間 | 5,399 ms |
コンパイル使用メモリ | 67,060 KB |
実行使用メモリ | 16,532 KB |
最終ジャッジ日時 | 2024-06-17 21:59:32 |
合計ジャッジ時間 | 8,511 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,816 KB |
testcase_01 | AC | 3 ms
6,812 KB |
testcase_02 | AC | 2 ms
6,816 KB |
testcase_03 | AC | 2 ms
6,944 KB |
testcase_04 | AC | 2 ms
6,944 KB |
testcase_05 | AC | 2 ms
6,940 KB |
testcase_06 | AC | 2 ms
6,940 KB |
testcase_07 | AC | 2 ms
6,940 KB |
testcase_08 | AC | 3 ms
6,944 KB |
testcase_09 | AC | 3 ms
6,940 KB |
testcase_10 | AC | 2 ms
6,944 KB |
testcase_11 | AC | 132 ms
15,488 KB |
testcase_12 | AC | 93 ms
14,080 KB |
testcase_13 | AC | 105 ms
11,648 KB |
testcase_14 | AC | 80 ms
10,240 KB |
testcase_15 | AC | 95 ms
13,824 KB |
testcase_16 | AC | 129 ms
16,256 KB |
testcase_17 | AC | 138 ms
16,532 KB |
testcase_18 | AC | 151 ms
16,384 KB |
ソースコード
import macros;macro ImportExpand(s:untyped):untyped = parseStmt($s[2]) # verification-helper: PROBLEM https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=3382 ImportExpand "cplib/collections/segtree.nim" <=== "when not declared CPLIB_COLLECTIONS_SEGTREE:\n const CPLIB_COLLECTIONS_SEGTREE* = 1\n import algorithm\n import strutils\n type SegmentTree*[T] = ref object\n default: T\n merge: proc(x: T, y: T): T\n arr*: seq[T]\n lastnode: int\n length: int\n proc initSegmentTree*[T](v: seq[T], merge: proc(x: T, y: T): T, default: T): SegmentTree[T] =\n ## セグメントツリーを生成します。\n ## vに元となるリスト、mergeに二つの区間をマージする関数、デフォルトに単位元を与えてください。\n var lastnode = 1\n while lastnode < len(v):\n lastnode*=2\n var arr = newSeq[T](2*lastnode)\n arr.fill(default)\n var self = SegmentTree[T](default: default, merge: merge, arr: arr, lastnode: lastnode, length: len(v))\n #1-indexedで作成する\n for i in 0..<len(v):\n self.arr[self.lastnode+i] = v[i]\n for i in countdown(lastnode-1, 1):\n self.arr[i] = self.merge(self.arr[2*i], self.arr[2*i+1])\n return self\n\n proc update*[T](self: SegmentTree[T], x: Natural, val: T) =\n ## xの要素をvalに変更します。\n assert x < self.length\n var x = x\n x += self.lastnode\n self.arr[x] = val\n while x > 1:\n x = x shr 1\n self.arr[x] = self.merge(self.arr[2*x], self.arr[2*x+1])\n proc get*[T](self: SegmentTree[T], q_left: Natural, q_right: Natural): T =\n ## 半解区間[q_left,q_right)についての演算結果を返します。\n assert q_left <= q_right and 0 <= q_left and q_right <= self.length\n var q_left = q_left\n var q_right = q_right\n q_left += self.lastnode\n q_right += self.lastnode\n var (lres, rres) = (self.default, self.default)\n while q_left < q_right:\n if (q_left and 1) > 0:\n lres = self.merge(lres, self.arr[q_left])\n q_left += 1\n if (q_right and 1) > 0:\n q_right -= 1\n rres = self.merge(self.arr[q_right], rres)\n q_left = q_left shr 1\n q_right = q_right shr 1\n return self.merge(lres, rres)\n proc get*[T](self: SegmentTree[T], segment: HSlice[int, int]): T =\n assert segment.a <= segment.b + 1 and 0 <= segment.a and segment.b+1 <= self.length\n return self.get(segment.a, segment.b+1)\n proc `[]`*[T](self: SegmentTree[T], segment: HSlice[int, int]): T = self.get(segment)\n proc `[]`*[T](self: SegmentTree[T], index: Natural): T =\n assert index < self.length\n return self.arr[index+self.lastnode]\n proc `[]=`*[T](self: SegmentTree[T], index: Natural, val: T) =\n assert index < self.length\n self.update(index, val)\n proc get_all*[T](self: SegmentTree[T]): T =\n ## [0,len(self))区間の演算結果をO(1)で返す\n return self.arr[1]\n proc len*[T](self: SegmentTree[T]): int =\n return self.length\n proc `$`*[T](self: SegmentTree[T]): string =\n var s = self.arr.len div 2\n return self.arr[s..<s+self.len].join(\" \")\n template newSegWith*(V, merge, default: untyped): untyped =\n initSegmentTree(V, proc (l{.inject.}, r{.inject.}: typeof(default)): typeof(default) = merge, default)\n proc max_right*[T](self: SegmentTree[T], l: int, f: proc(l: T): bool): int =\n assert 0 <= l and l <= self.len\n assert f(self.default)\n var l = l\n if l == self.len: return self.len\n l += self.lastnode\n var sm = self.default\n while true:\n while l mod 2 == 0: l = (l shr 1)\n if not f(self.merge(sm, self.arr[l])):\n while l < self.lastnode:\n l *= 2\n if f(self.merge(sm, self.arr[l])):\n sm = self.merge(sm, self.arr[l])\n l += 1\n return l - self.lastnode\n sm = self.merge(sm, self.arr[l])\n l += 1\n if (l and -l) == l: break\n return self.len\n\n" import sequtils import strutils import algorithm proc scanf(formatstr: cstring){.header: "<stdio.h>", varargs.} proc ii(): int {.inline.} = scanf("%lld\n", addr result) var n, q = ii() var a = newSeqWith(n, ii()) a.reverse var seg = newSegWith(a, max(l, r), 0) var mn = newSeq[int](n) for i in 0..<n: var l = n-1-i var mx = seg.max_right(l+1, proc(x: int): bool = x <= a[l]) mn[i] = n-mx var ad = newseqwith(n, newseq[int]()) for i in 0..<n: ad[mn[i]].add(i) a.reverse var query = newSeq[(int,int,int)](q) for i in 0..<q: var _, l, r = ii() query[i] = (l-1, r, i) query.sort var ans = newseq[int](q) var seg_add = newsegwith(newseqwith(n, 0), l+r, 0) var li = 0 for (l, r, id) in query: while li <= l: for x in ad[li]: seg_add[x] = seg_add[x] + 1 li += 1 ans[id] = seg_add[l..<r] echo ans.join("\n")