← Home
For problem statement at 0-999/900-999/930-939/935/problemF.txt this is a correct solution, but verifier at 0-999/900-999/930-939/935/verifierF.go ends with All tests passed can you fix the verifier? package main

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

type Node struct {
	lmax bool
	hasU bool
	mBU  int64
	hasD bool
	mAD  int64
	hasM bool
	mSum int64
	mAM  int64
	mBM  int64
}

const INF int64 = 1<<60

func abs64(x int64) int64 {
	if x < 0 {
		return -x
	}
	return x
}

func min64(a, b int64) int64 {
	if a < b {
		return a
	}
	return b
}

func max64(a, b int64) int64 {
	if a > b {
		return a
	}
	return b
}

type SegTree struct {
	n   int
	t   []Node
	d   []int64
	nv  int
	idn Node
}

func (st *SegTree) init(d []int64) {
	st.d = d
	st.nv = len(d) - 1 // number of leaves = n-2 if len(a)=n
	if st.nv <= 0 {
		st.nv = 0
	}
	st.t = make([]Node, 4*maxInt(1, st.nv))
	st.idn = Node{false, false, INF, false, INF, false, INF, INF, INF}
	if st.nv > 0 {
		st.build(1, 0, st.nv-1)
	}
}

func (st *SegTree) leafFromIndex(idx int) Node {
	A := st.d[idx]
	B := st.d[idx+1]
	var nd Node
	if A >= 0 && B <= 0 {
		nd.lmax = true
	}
	if A >= 0 && B > 0 {
		nd.hasU = true
		nd.mBU = B
	} else {
		nd.mBU = INF
	}
	if A < 0 && B <= 0 {
		nd.hasD = true
		nd.mAD = -A
	} else {
		nd.mAD = INF
	}
	if A < 0 && B > 0 {
		nd.hasM = true
		nd.mSum = -A + B
		nd.mAM = -A
		nd.mBM = B
	} else {
		nd.mSum = INF
		nd.mAM = INF
		nd.mBM = INF
	}
	return nd
}

func (st *SegTree) merge(a, b Node) Node {
	var r Node
	r.lmax = a.lmax || b.lmax
	r.hasU = a.hasU || b.hasU
	r.mBU = min64(a.mBU, b.mBU)
	r.hasD = a.hasD || b.hasD
	r.mAD = min64(a.mAD, b.mAD)
	r.hasM = a.hasM || b.hasM
	r.mSum = min64(a.mSum, b.mSum)
	r.mAM = min64(a.mAM, b.mAM)
	r.mBM = min64(a.mBM, b.mBM)
	return r
}

func (st *SegTree) build(v, l, r int) {
	if l == r {
		st.t[v] = st.leafFromIndex(l)
		return
	}
	m := (l + r) >> 1
	st.build(v<<1, l, m)
	st.build(v<<1|1, m+1, r)
	st.t[v] = st.merge(st.t[v<<1], st.t[v<<1|1])
}

func (st *SegTree) update(pos int) {
	if st.nv == 0 {
		return
	}
	st._update(1, 0, st.nv-1, pos, st.leafFromIndex(pos))
}

func (st *SegTree) _update(v, l, r, pos int, val Node) {
	if l == r {
		st.t[v] = val
		return
	}
	m := (l + r) >> 1
	if pos <= m {
		st._update(v<<1, l, m, pos, val)
	} else {
		st._update(v<<1|1, m+1, r, pos, val)
	}
	st.t[v] = st.merge(st.t[v<<1], st.t[v<<1|1])
}

func (st *SegTree) query(ql, qr int) Node {
	if st.nv == 0 {
		return st.idn
	}
	return st._query(1, 0, st.nv-1, ql, qr)
}

func (st *SegTree) _query(v, l, r, ql, qr int) Node {
	if ql <= l && r <= qr {
		return st.t[v]
	}
	if r < ql || qr < l {
		return st.idn
	}
	m := (l + r) >> 1
	ln := st._query(v<<1, l, m, ql, qr)
	rn := st._query(v<<1|1, m+1, r, ql, qr)
	return st.merge(ln, rn)
}

func maxInt(a, b int) int {
	if a > b {
		return a
	}
	return b
}

type FastScanner struct {
	r *bufio.Reader
}

func NewFastScanner() *FastScanner {
	return &FastScanner{r: bufio.NewReaderSize(os.Stdin, 1<<20)}
}

func (fs *FastScanner) nextInt64() int64 {
	var sign int64 = 1
	var val int64 = 0
	c, err := fs.r.ReadByte()
	for (c < '0' || c > '9') && c != '-' {
		c, err = fs.r.ReadByte()
		if err != nil {
			return 0
		}
	}
	if c == '-' {
		sign = -1
		c, _ = fs.r.ReadByte()
	}
	for c >= '0' && c <= '9' {
		val = val*10 + int64(c-'0')
		c, err = fs.r.ReadByte()
		if err != nil {
			break
		}
	}
	return sign * val
}

func main() {
	fs := NewFastScanner()
	out := bufio.NewWriterSize(os.Stdout, 1<<20)
	defer out.Flush()

	n := int(fs.nextInt64())
	a := make([]int64, n)
	for i := 0; i < n; i++ {
		a[i] = fs.nextInt64()
	}
	d := make([]int64, n-1)
	var S int64 = 0
	for i := 0; i < n-1; i++ {
		d[i] = a[i+1] - a[i]
		S += abs64(d[i])
	}
	seg := &SegTree{}
	seg.init(d)

	q := int(fs.nextInt64())
	for ; q > 0; q-- {
		t := int(fs.nextInt64())
		l := int(fs.nextInt64())
		r := int(fs.nextInt64())
		x := fs.nextInt64()
		if t == 1 {
			L := l - 2
			R := r - 2
			res := seg.query(L, R)
			gain := int64(-1 << 62)
			twoX := 2 * x
			if res.lmax {
				gain = max64(gain, twoX)
			}
			if res.hasU {
				gain = max64(gain, twoX-2*res.mBU)
			}
			if res.hasD {
				gain = max64(gain, twoX-2*res.mAD)
			}
			if res.hasM {
				gain = max64(gain, twoX-2*res.mSum)
				gain = max64(gain, -twoX)
				mm := res.mAM
				if res.mBM < mm {
					mm = res.mBM
				}
				gain = max64(gain, -2*mm)
			}
			if res.hasU || res.hasD {
				gain = max64(gain, 0)
			}
			fmt.Fprintln(out, S+gain)
		} else {
			j1 := l - 1
			k1 := j1 - 1
			old1 := d[k1]
			d[k1] = old1 + x
			S += abs64(d[k1]) - abs64(old1)

			j2 := r
			k2 := j2 - 1
			old2 := d[k2]
			d[k2] = old2 - x
			S += abs64(d[k2]) - abs64(old2)

			// update leaves for i = j1, j1+1, j2, j2+1 where 2 <= i <= n-1
			if j1 >= 2 && j1 <= n-1 {
				seg.update(j1 - 2)
			}
			if j1+1 >= 2 && j1+1 <= n-1 {
				seg.update(j1 - 1)
			}
			if j2 >= 2 && j2 <= n-1 {
				seg.update(j2 - 2)
			}
			if j2+1 >= 2 && j2+1 <= n-1 {
				seg.update(j2 - 1)
			}
		}
	}
}