結果

問題 No.1441 MErGe
ユーザー 草苺奶昔草苺奶昔
提出日時 2024-09-11 00:53:22
言語 Go
(1.22.1)
結果
AC  
実行時間 911 ms / 1,000 ms
コード長 11,003 bytes
コンパイル時間 18,275 ms
コンパイル使用メモリ 233,876 KB
実行使用メモリ 24,844 KB
最終ジャッジ日時 2024-09-11 00:53:59
合計ジャッジ時間 35,333 ms
ジャッジサーバーID
(参考情報)
judge1 / judge3
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,812 KB
testcase_01 AC 2 ms
6,816 KB
testcase_02 AC 1 ms
6,944 KB
testcase_03 AC 6 ms
6,944 KB
testcase_04 AC 7 ms
6,940 KB
testcase_05 AC 17 ms
6,940 KB
testcase_06 AC 18 ms
6,940 KB
testcase_07 AC 18 ms
6,940 KB
testcase_08 AC 193 ms
9,968 KB
testcase_09 AC 217 ms
7,836 KB
testcase_10 AC 337 ms
7,964 KB
testcase_11 AC 300 ms
7,840 KB
testcase_12 AC 328 ms
10,096 KB
testcase_13 AC 708 ms
24,844 KB
testcase_14 AC 720 ms
22,800 KB
testcase_15 AC 737 ms
24,836 KB
testcase_16 AC 689 ms
20,632 KB
testcase_17 AC 686 ms
22,736 KB
testcase_18 AC 541 ms
20,628 KB
testcase_19 AC 586 ms
22,740 KB
testcase_20 AC 466 ms
14,408 KB
testcase_21 AC 428 ms
16,344 KB
testcase_22 AC 582 ms
16,472 KB
testcase_23 AC 904 ms
22,740 KB
testcase_24 AC 857 ms
22,820 KB
testcase_25 AC 859 ms
22,740 KB
testcase_26 AC 884 ms
22,820 KB
testcase_27 AC 911 ms
22,744 KB
testcase_28 AC 410 ms
20,692 KB
testcase_29 AC 411 ms
20,648 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

// 维护区间和的 splay 树. monoid 不要求满足交换律.
// api
// - NewSpalyTreeMonoid() *SplayTreeMonoid
// - NewRoot() *SplayNode
// - Build(n int32, f func(i int32) E) *SplayNode
// - Size(n *SplayNode) int32
// - Merge(l, r *SplayNode) *SplayNode
// - Split(root *SplayNode, k int32) (*SplayNode, *SplayNode)
// - EnumerateAll(root *SplayNode, f func(E))
// - Get(root **SplayNode, k int32) E
// - Set(root **SplayNode, k int32, x E)
// - Update(root **SplayNode, k int32, x E)
// - QueryRange(root **SplayNode, l, r int32) E
// - QueryAll(root *SplayNode) E
// - Reverse(root **SplayNode, l, r int32)
// - ReverseAll(root *SplayNode)
//
// - SplitMaxRightByValue(root *SplayNode, check func(E) bool) (*SplayNode, *SplayNode)
// - SplitMaxRightByValueAndCount(root *SplayNode, check func(E, int32) bool) (*SplayNode, *SplayNode)
// - SplitMaxRightBySum(root *SplayNode, check func(E) bool) (*SplayNode, *SplayNode)

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	yuki1441()
}

func demo() {
	S := NewSpalyTreeMonoid()
	nums := S.Build(10, func(i int32) E { return E(i) })
	S.Update(&nums, 0, 1)
	S.Update(&nums, 1, 2)
	S.Update(&nums, 2, 3)
	S.Set(&nums, 3, 4)

	getAll := func() []E {
		res := []E{}
		S.EnumerateAll(nums, func(x E) {
			res = append(res, x)
		})
		return res
	}

	fmt.Println(getAll())

	fmt.Println(S.QueryRange(&nums, 0, 4))
	fmt.Println(S.QueryAll(nums))
	fmt.Println(S.Get(&nums, 3))
}

func yuki1441() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

	var n, q int
	fmt.Fscan(in, &n, &q)

	A := make([]E, n)
	for i := 0; i < n; i++ {
		fmt.Fscan(in, &A[i])
	}

	S := NewSpalyTreeMonoid()
	root := S.Build(int32(n), func(i int32) E { return A[i] })

	for i := 0; i < q; i++ {
		var t, l, r int
		fmt.Fscan(in, &t, &l, &r)
		l--
		if t == 1 {
			S.gotoBetween(&root, int32(l), int32(r))
			root.l = nil
			root.r = nil
			root.x = root.sum
			S.nodePushup(root)
			S.splay(root, true)
		}
		if t == 2 {
			fmt.Fprintln(out, S.QueryRange(&root, int32(l), int32(r)))
		}
	}
}

type E = int

func e() E        { return 0 }
func op(a, b E) E { return a + b }

func NewSpalyTreeMonoid() *SplayTreeMonoid {
	return &SplayTreeMonoid{}
}

type SplayNode struct {
	rev            bool
	size           int32
	x, sum, revSum E
	p, l, r        *SplayNode
}

type SplayTreeMonoid struct{}

func (st *SplayTreeMonoid) NewRoot() *SplayNode {
	return nil
}

func (st *SplayTreeMonoid) Build(n int32, f func(i int32) E) *SplayNode {
	var dfs func(l, r int32) *SplayNode
	dfs = func(l, r int32) *SplayNode {
		if l == r {
			return nil
		}
		if r == l+1 {
			return st.newNode(f(l))
		}
		m := (l + r) >> 1
		lRoot, rRoot := dfs(l, m), dfs(m+1, r)
		root := st.newNode(f(m))
		root.l, root.r = lRoot, rRoot
		if lRoot != nil {
			lRoot.p = root
		}
		if rRoot != nil {
			rRoot.p = root
		}
		st.nodePushup(root)
		return root
	}
	return dfs(0, n)
}

func (st *SplayTreeMonoid) Size(n *SplayNode) int32 {
	if n == nil {
		return 0
	}
	return n.size
}

func (st *SplayTreeMonoid) Merge(l, r *SplayNode) *SplayNode {
	if l == nil {
		return r
	}
	if r == nil {
		return l
	}
	st.splayKth(&r, 0)
	r.l = l
	l.p = r
	st.nodePushup(r)
	return r
}

func (st *SplayTreeMonoid) Merge3(a, b, c *SplayNode) *SplayNode {
	return st.Merge(st.Merge(a, b), c)
}

func (st *SplayTreeMonoid) Merge4(a, b, c, d *SplayNode) *SplayNode {
	return st.Merge(st.Merge(st.Merge(a, b), c), d)
}

func (st *SplayTreeMonoid) Split(root *SplayNode, k int32) (*SplayNode, *SplayNode) {
	if k == 0 {
		return nil, root
	}
	if k == root.size {
		return root, nil
	}
	st.splayKth(&root, k-1)
	right := root.r
	root.r = nil
	root.p = nil
	st.nodePushup(root)
	return root, right
}

func (st *SplayTreeMonoid) Split3(root *SplayNode, l, r int32) (*SplayNode, *SplayNode, *SplayNode) {
	var nm, nr *SplayNode
	root, nr = st.Split(root, r)
	root, nm = st.Split(root, l)
	return root, nm, nr
}

func (st *SplayTreeMonoid) Split4(root *SplayNode, i, j, k int32) (*SplayNode, *SplayNode, *SplayNode, *SplayNode) {
	var d *SplayNode
	root, d = st.Split(root, k)
	a, b, c := st.Split3(root, i, j)
	return a, b, c, d
}

func (st *SplayTreeMonoid) EnumerateAll(root *SplayNode, f func(E)) {
	var dfs func(*SplayNode)
	dfs = func(root *SplayNode) {
		if root == nil {
			return
		}
		st.nodePushdown(root)
		dfs(root.l)
		f(st.nodeGet(root))
		dfs(root.r)
	}
	dfs(root)
}
func (st *SplayTreeMonoid) GetAll(root *SplayNode) []E {
	if root == nil {
		return nil
	}
	res := make([]E, 0, root.size)
	st.EnumerateAll(root, func(v E) { res = append(res, v) })
	return res
}
func (st *SplayTreeMonoid) Get(root **SplayNode, k int32) E {
	st.splayKth(root, k)
	return st.nodeGet(*root)
}

func (st *SplayTreeMonoid) Set(root **SplayNode, k int32, x E) {
	st.splayKth(root, k)
	st.nodeSet(*root, x)
}

func (st *SplayTreeMonoid) Update(root **SplayNode, k int32, x E) {
	st.splayKth(root, k)
	st.nodeUpdate(*root, x)
}

func (st *SplayTreeMonoid) Reverse(root **SplayNode, l, r int32) {
	if l == r {
		return
	}
	if l < 0 {
		l = 0
	}
	if s := (*root).size; r > s {
		r = s
	}
	if l >= r {
		return
	}
	st.gotoBetween(root, l, r)
	st.nodeReverse(*root)
	st.splay(*root, true)
}

func (st *SplayTreeMonoid) ReverseAll(root *SplayNode) {
	if root != nil {
		st.nodeReverse(root)
	}
}

func (st *SplayTreeMonoid) QueryRange(root **SplayNode, l, r int32) E {
	if l == r {
		return e()
	}
	if l < 0 {
		l = 0
	}
	if s := (*root).size; r > s {
		r = s
	}
	if l >= r {
		return e()
	}
	st.gotoBetween(root, l, r)
	res := (*root).sum
	st.splay(*root, true)
	return res
}

func (st *SplayTreeMonoid) QueryAll(root *SplayNode) E {
	if root == nil {
		return e()
	}
	return root.sum
}

func (st *SplayTreeMonoid) gotoBetween(root **SplayNode, l, r int32) {
	if l == 0 && r == (*root).size {
		return
	}
	if l == 0 {
		st.splayKth(root, r)
		*root = (*root).l
		return
	}
	if r == (*root).size {
		st.splayKth(root, l-1)
		*root = (*root).r
		return
	}
	st.splayKth(root, r)
	rp := *root
	(*root) = rp.l
	(*root).p = nil
	st.splayKth(root, l-1)
	(*root).p = rp
	rp.l = *root
	st.nodePushup(rp)
	*root = (*root).r
}

func (st *SplayTreeMonoid) rotate(n *SplayNode) {
	var pp, p, c *SplayNode
	p = n.p
	pp = p.p
	if p.l == n {
		c = n.r
		n.r = p
		p.l = c
	} else {
		c = n.l
		n.l = p
		p.r = c
	}
	if pp != nil && pp.l == p {
		pp.l = n
	}
	if pp != nil && pp.r == p {
		pp.r = n
	}
	n.p = pp
	p.p = n
	if c != nil {
		c.p = p
	}
}

func (st *SplayTreeMonoid) propFromRoot(c *SplayNode) {
	if c.p == nil {
		st.nodePushdown(c)
		return
	}
	st.propFromRoot(c.p)
	st.nodePushdown(c)
}

func (st *SplayTreeMonoid) splay(me *SplayNode, propFromRootDone bool) {
	if !propFromRootDone {
		st.propFromRoot(me)
	}
	st.nodePushdown(me)
	for me.p != nil {
		p := me.p
		pp := p.p
		if pp == nil {
			st.rotate(me)
			st.nodePushup(p)
			break
		}
		same := (p.l == me && pp.l == p) || (p.r == me && pp.r == p)
		if same {
			st.rotate(p)
			st.rotate(me)
		} else {
			st.rotate(me)
		}
		st.nodePushup(pp)
		st.nodePushup(p)
	}
	st.nodePushup(me)
}

func (st *SplayTreeMonoid) splayKth(root **SplayNode, k int32) {
	for {
		st.nodePushdown(*root)
		sl := st.Size((*root).l)
		if k == sl {
			break
		}
		if k < sl {
			*root = (*root).l
		} else {
			k -= sl + 1
			*root = (*root).r
		}
	}
	st.splay(*root, true)
}

// 分离出的左侧节点值满足check函数.
func (st *SplayTreeMonoid) SplitMaxRightByValue(root *SplayNode, check func(E) bool) (*SplayNode, *SplayNode) {
	if root == nil {
		return nil, nil
	}
	c := st.findMaxRightByValue(root, check)
	if c == nil {
		st.splay(root, true)
		return nil, root
	}
	st.splay(c, true)
	right := c.r
	if right == nil {
		return c, nil
	}
	right.p = nil
	c.r = nil
	st.nodePushup(c)
	return c, right
}

// 分离出的左侧节点之和与
func (st *SplayTreeMonoid) SplitMaxRightByValueAndCount(root *SplayNode, check func(E, int32) bool) (*SplayNode, *SplayNode) {
	if root == nil {
		return nil, nil
	}
	c := st.findMaxRightByValueAndCount(root, check)
	if c == nil {
		st.splay(root, true)
		return nil, root
	}
	st.splay(c, true)
	right := c.r
	if right == nil {
		return c, nil
	}
	right.p = nil
	c.r = nil
	st.nodePushup(c)
	return c, right
}

// 分离出的左侧节点之和满足check函数.
func (st *SplayTreeMonoid) SplitMaxRightBySum(root *SplayNode, check func(E) bool) (*SplayNode, *SplayNode) {
	if root == nil {
		return nil, nil
	}
	c := st.findMaxRightBySum(root, check)
	if c == nil {
		st.splay(root, true)
		return nil, root
	}
	st.splay(c, true)
	right := c.r
	if right == nil {
		return c, nil
	}
	right.p = nil
	c.r = nil
	st.nodePushup(c)
	return c, right
}

func (st *SplayTreeMonoid) findMaxRightByValue(root *SplayNode, check func(E) bool) *SplayNode {
	var lastOk, last *SplayNode
	for root != nil {
		last = root
		st.nodePushdown(root)
		if check(root.x) {
			lastOk = root
			root = root.r
		} else {
			root = root.l
		}
	}
	st.splay(last, true)
	return lastOk
}

func (st *SplayTreeMonoid) findMaxRightByValueAndCount(root *SplayNode, check func(E, int32) bool) *SplayNode {
	var lastOk, last *SplayNode
	var n int32
	for root != nil {
		last = root
		st.nodePushdown(root)
		ns := st.Size(root.l)
		if check(root.x, n+ns+1) {
			lastOk = root
			n += ns + 1
			root = root.r
		} else {
			root = root.l
		}
	}
	st.splay(last, true)
	return lastOk
}

func (st *SplayTreeMonoid) findMaxRightBySum(root *SplayNode, check func(E) bool) *SplayNode {
	prod := e()
	var lastOk, last *SplayNode
	for root != nil {
		last = root
		st.nodePushdown(root)
		lprod := prod
		if root.l != nil {
			lprod = op(lprod, root.l.sum)
		}
		lprod = op(lprod, root.x)
		if check(lprod) {
			prod = lprod
			lastOk = root
			root = root.r
		} else {
			root = root.l
		}
	}
	st.splay(last, true)
	return lastOk
}

// 私有方法需要重写
func (st *SplayTreeMonoid) newNode(x E) *SplayNode {
	return &SplayNode{x: x, sum: x, revSum: x, size: 1}
}

func (st *SplayTreeMonoid) nodePushup(n *SplayNode) {
	n.size = 1
	n.sum = n.x
	n.revSum = n.x
	if n.l != nil {
		n.size += n.l.size
		n.sum = op(n.l.sum, n.sum)
		n.revSum = op(n.revSum, n.l.revSum)
	}
	if n.r != nil {
		n.size += n.r.size
		n.sum = op(n.sum, n.r.sum)
		n.revSum = op(n.r.revSum, n.revSum)
	}
}

func (st *SplayTreeMonoid) nodePushdown(n *SplayNode) {
	if n.rev {
		if left := n.l; left != nil {
			left.rev = !left.rev
			left.l, left.r = left.r, left.l
			left.sum, left.revSum = left.revSum, left.sum
		}
		if right := n.r; right != nil {
			right.rev = !right.rev
			right.l, right.r = right.r, right.l
			right.sum, right.revSum = right.revSum, right.sum
		}
		n.rev = false
	}
}

func (st *SplayTreeMonoid) nodeGet(n *SplayNode) E {
	return n.x
}

func (st *SplayTreeMonoid) nodeSet(n *SplayNode, x E) {
	n.x = x
	st.nodePushup(n)
}

func (st *SplayTreeMonoid) nodeUpdate(n *SplayNode, x E) {
	n.x = op(n.x, x)
	st.nodePushup(n)
}

func (st *SplayTreeMonoid) nodeReverse(n *SplayNode) {
	n.sum, n.revSum = n.revSum, n.sum
	n.l, n.r = n.r, n.l
	n.rev = !n.rev
}
0