#{{{ header import algorithm, sequtils, tables, macros, math, sets, strutils when defined(MYDEBUG): import header proc scanf(formatstr: cstring){.header: "", varargs.} proc getchar(): char {.header: "", varargs.} proc nextInt(): int = scanf("%lld",addr result) proc nextFloat(): float = scanf("%lf",addr result) proc nextString(): string = var get = false result = "" while true: var c = getchar() if int(c) > int(' '): get = true result.add(c) else: if get: break get = false template `max=`*(x,y:typed):void = x = max(x,y) template `min=`*(x,y:typed):void = x = min(x,y) template infty(T): untyped = ((T(1) shl T(sizeof(T)*8-2)) - 1) #}}} import random var rnd = initRand(2019) #type Xor128 = object # x,y,z,w:int # #proc newXor128():Xor128 = # return Xor128(x:123456789,y:362436069, z:521288629, w:88675123) # #proc next(a:var Xor128):int = # var # x:ref int # y:ref int # z:ref int # w:ref int # x[] = a.x # y[] = a.y # z[] = a.z # w[] = a.w # var # t = x[] xor (x[] shl 11) # x[] = y[] # y[] = z[] # z[] = w[] # w[] = (w[] xor (w[] shr 19)) xor (t xor (t shr 8)) # return w[] #template< class S, class T = S > #struct RandomizedBinarySearchTree { ## using F = function< S(S, S) >; ## using G = function< S(S, T) >; ## using H = function< T(T, T) >; ## using P = function< T(T, int) >; # # type Node[S,T] = ref object l,r: Node[S,T] cnt: int key, sum: S lazy: T RBST[S,T] = ref object of RootObj M1: S OM0: T f: proc(x,y:S):S g: proc(x:S,y:T):S h: proc(x,y:T):T p: proc(x:T,y:int):T {.this: self.} proc newNode[S, T](k:S, p:T): Node[S, T] = return Node[S, T](cnt:1, key:k, sum:k, lazy:p, l:nil, r:nil) proc newRBST[S](f:proc(x,y:S):S, M1:S):RBST[S, S] = return RBST[S, S](M1:M1,f:f) #proc newRBST[S, T](M1:S, OM0:T):RBST[S, T] = # return RBST[S, T](M1:M1,OM0:OM0) proc alloc[S, T](self:RBST[S,T], key:S):Node[S,T] = return newNode[S,T](key, self.OM0) proc clone[S,T](self:RBST[S,T], t:Node[S,T]):Node[S,T] = return t proc count[S,T](self:RBST[S,T], t:Node):int = if t != nil: return t.cnt else: return 0 proc sum[S,T](self:RBST[S,T], t:Node[S,T]):S = if t != nil: return t.sum else: return self.M1 proc update[S,T](self:RBST[S,T], t:Node[S,T]):Node[S,T] = t.cnt = count(t.l) + count(t.r) + 1 t.sum = self.f(self.f(sum(t.l), t.key), sum(t.r)) return t proc propagate[S,T](self:RBST[S,T], t2:Node[S,T]):Node[S,T] = var t = clone(t2) if t.lazy != self.OM0: t.key = self.g(t.key, t.lazy) if t.l!=nil: t.l = clone(t.l) t.l.lazy = self.h(t.l.lazy, t.lazy) t.l.sum = self.f(t.l.sum, self.p(t.lazy, count(t.l))) if t.r != nil: t.r = clone(t.r) t.r.lazy = self.h(t.r.lazy, t.lazy) t.r.sum = self.f(self.p(t.lazy, count(t.r)), t.r.sum) t.lazy = self.OM0 return update(t) proc merge[S,T](self:RBST[S,T], l2,r2: Node[S,T]): Node[S,T] = if l2 == nil: return r2 elif r2 == nil: return l2 var l = l2 r = r2 if rnd.rand(0..10^18) mod (l.cnt + r.cnt) < l.cnt: l = self.propagate(l) l.r = self.merge(l.r, r) return update(l) else: r = self.propagate(r); r.l = self.merge(l, r.l) return update(r); proc split[S,T](self:RBST[S,T], t:var Node[S,T], k:int):(Node[S,T],Node[S,T]) = if t == nil: return (nil,nil) t = self.propagate(t); if k <= count(t.l): var s = self.split(t.l, k) t.l = s[1] return (s[0], self.update(t)) else: var s = self.split(t.r, k - self.count(t.l) - 1) t.r = s[0] return (update(t), s[1]) proc build[S,T](self:RBST[S,T],l,r:int, v: seq[S]):Node[S,T] = if l + 1 >= r: return self.alloc(v[l]) var nl = self.build(l, (l + r) shr 1, v) nr = self.build((l + r) shr 1, r, v) return self.merge(nl, nr) proc build[S,T](self:RBST[S,T], v: seq[S]):Node[S,T] = return self.build(0, v.len, v) # # vector< Node > pool; # int ptr; # # const S M1; # const T OM0; # const F f; # const G g; # const H h; # const P p; # # RandomizedBinarySearchTree(int sz, const F &f, const S &M1) : # pool(sz), ptr(0), f(f), g(G()), h(H()), p(P()), M1(M1), OM0(T()) {} # # RandomizedBinarySearchTree(int sz, const F &f, const G &g, const H &h, const P &p, # const S &M1, const T &OM0) : # pool(sz), ptr(0), f(f), g(g), h(h), p(p), M1(M1), OM0(OM0) {} # # # proc dump[S,T](self:RBST[S,T], r:var Node[S,T], i:var int, v:var seq[S]):void = if r == nil: return r = self.propagate(r) self.dump(r.l, i, v) v[i] = r.key i += 1 self.dump(r.r, i, v) proc dump[S,T](self:RBST[S,T], r:var Node[S,T]):seq[S] = result = newSeq[S](self.count(r)) var i = 0 self.dump(r, i, result) proc to_string[S,T](self:RBST[S,T], r:var Node[S,T]):string = var s = self.dump(r) result = "" for i in 0..