結果
問題 | No.776 A Simple RMQ Problem |
ユーザー | koba-e964 |
提出日時 | 2021-09-27 16:23:14 |
言語 | Rust (1.77.0 + proconio) |
結果 |
AC
|
実行時間 | 430 ms / 3,000 ms |
コード長 | 8,760 bytes |
コンパイル時間 | 21,380 ms |
コンパイル使用メモリ | 388,424 KB |
実行使用メモリ | 19,072 KB |
最終ジャッジ日時 | 2024-07-06 12:08:58 |
合計ジャッジ時間 | 33,901 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1 ms
5,248 KB |
testcase_01 | AC | 1 ms
5,248 KB |
testcase_02 | AC | 45 ms
6,144 KB |
testcase_03 | AC | 188 ms
17,756 KB |
testcase_04 | AC | 193 ms
6,400 KB |
testcase_05 | AC | 329 ms
18,036 KB |
testcase_06 | AC | 90 ms
9,600 KB |
testcase_07 | AC | 206 ms
18,272 KB |
testcase_08 | AC | 250 ms
9,856 KB |
testcase_09 | AC | 82 ms
18,400 KB |
testcase_10 | AC | 173 ms
9,996 KB |
testcase_11 | AC | 293 ms
18,580 KB |
testcase_12 | AC | 360 ms
18,912 KB |
testcase_13 | AC | 344 ms
18,944 KB |
testcase_14 | AC | 341 ms
18,896 KB |
testcase_15 | AC | 339 ms
18,780 KB |
testcase_16 | AC | 339 ms
18,860 KB |
testcase_17 | AC | 430 ms
18,944 KB |
testcase_18 | AC | 265 ms
18,856 KB |
testcase_19 | AC | 382 ms
19,072 KB |
testcase_20 | AC | 393 ms
19,052 KB |
testcase_21 | AC | 386 ms
18,892 KB |
testcase_22 | AC | 388 ms
18,848 KB |
testcase_23 | AC | 387 ms
18,832 KB |
testcase_24 | AC | 383 ms
18,816 KB |
testcase_25 | AC | 56 ms
5,376 KB |
testcase_26 | AC | 256 ms
18,944 KB |
testcase_27 | AC | 233 ms
18,712 KB |
ソースコード
#[allow(unused_imports)] use std::cmp::*; #[allow(unused_imports)] use std::collections::*; use std::io::Read; #[allow(dead_code)] fn getline() -> String { let mut ret = String::new(); std::io::stdin().read_line(&mut ret).ok().unwrap(); ret } fn get_word() -> String { let stdin = std::io::stdin(); let mut stdin=stdin.lock(); let mut u8b: [u8; 1] = [0]; loop { let mut buf: Vec<u8> = Vec::with_capacity(16); loop { let res = stdin.read(&mut u8b); if res.unwrap_or(0) == 0 || u8b[0] <= b' ' { break; } else { buf.push(u8b[0]); } } if buf.len() >= 1 { let ret = String::from_utf8(buf).unwrap(); return ret; } } } #[allow(dead_code)] fn get<T: std::str::FromStr>() -> T { get_word().parse().ok().unwrap() } /** * Segment Tree. This data structure is useful for fast folding on intervals of an array * whose elements are elements of monoid I. Note that constructing this tree requires the identity * element of I and the operation of I. * Verified by: yukicoder No. 259 (http://yukicoder.me/submissions/100581) * AGC015-E (http://agc015.contest.atcoder.jp/submissions/1461001) */ struct SegTree<I, BiOp> { n: usize, dat: Vec<I>, op: BiOp, e: I, } impl<I, BiOp> SegTree<I, BiOp> where BiOp: Fn(I, I) -> I, I: Copy { pub fn new(n_: usize, op: BiOp, e: I) -> Self { let mut n = 1; while n < n_ { n *= 2; } // n is a power of 2 SegTree {n: n, dat: vec![e; 2 * n - 1], op: op, e: e} } /* ary[k] <- v */ pub fn update(&mut self, idx: usize, v: I) { let mut k = idx + self.n - 1; self.dat[k] = v; while k > 0 { k = (k - 1) / 2; self.dat[k] = (self.op)(self.dat[2 * k + 1], self.dat[2 * k + 2]); } } /* [a, b) (note: half-inclusive) * http://proc-cpuinfo.fixstars.com/2017/07/optimize-segment-tree/ */ pub fn query(&self, mut a: usize, mut b: usize) -> I { let mut left = self.e; let mut right = self.e; a += self.n - 1; b += self.n - 1; while a < b { if (a & 1) == 0 { left = (self.op)(left, self.dat[a]); } if (b & 1) == 0 { right = (self.op)(self.dat[b - 1], right); } a = a / 2; b = (b - 1) / 2; } (self.op)(left, right) } } /** * Lazy Segment Tree. This data structure is useful for fast folding and updating on intervals of an array * whose elements are elements of monoid T. Note that constructing this tree requires the identity * element of T and the operation of T. This is monomorphised, because of efficiency. T := i64, biop = max, upop = (+) * Reference: http://d.hatena.ne.jp/kyuridenamida/20121114/1352835261 * Verified by https://codeforces.com/contest/1114/submission/49759034 */ pub trait ActionRing { type T: Clone + Copy; // data type U: Clone + Copy + PartialEq + Eq; // action fn biop(x: Self::T, y: Self::T) -> Self::T; fn update(x: Self::T, a: Self::U, height: usize) -> Self::T; fn upop(fst: Self::U, snd: Self::U) -> Self::U; fn e() -> Self::T; fn upe() -> Self::U; // identity for upop } pub struct LazySegTree<R: ActionRing> { n: usize, dep: usize, dat: Vec<R::T>, lazy: Vec<R::U>, } impl<R: ActionRing> LazySegTree<R> { #[allow(unused)] pub fn new(n_: usize) -> Self { let mut n = 1; let mut dep = 0; while n < n_ { n *= 2; dep += 1; } // n is a power of 2 LazySegTree { n: n, dep: dep, dat: vec![R::e(); 2 * n - 1], lazy: vec![R::upe(); 2 * n - 1] } } #[allow(unused)] pub fn with(a: &[R::T]) -> Self { let n_ = a.len(); let mut n = 1; let mut dep = 0; while n < n_ { n *= 2; dep += 1; } // n is a power of 2 let mut dat = vec![R::e(); 2 * n - 1]; for i in 0..n_ { dat[n - 1 + i] = a[i]; } for i in (0..n - 1).rev() { dat[i] = R::biop(dat[2 * i + 1], dat[2 * i + 2]); } LazySegTree { n: n, dep: dep, dat: dat, lazy: vec![R::upe(); 2 * n - 1], } } #[inline] fn lazy_evaluate_node(&mut self, k: usize, height: usize) { if self.lazy[k] == R::upe() { return; } self.dat[k] = R::update(self.dat[k], self.lazy[k], height); if k < self.n - 1 { self.lazy[2 * k + 1] = R::upop(self.lazy[2 * k + 1], self.lazy[k]); self.lazy[2 * k + 2] = R::upop(self.lazy[2 * k + 2], self.lazy[k]); } self.lazy[k] = R::upe(); // identity for upop } #[inline] fn update_node(&mut self, k: usize) { self.dat[k] = R::biop(self.dat[2 * k + 1], self.dat[2 * k + 2]); } fn update_sub(&mut self, a: usize, b: usize, v: R::U, k: usize, height: usize, l: usize, r: usize) { self.lazy_evaluate_node(k, height); // [a,b) and [l,r) intersects? if r <= a || b <= l {return;} if a <= l && r <= b { self.lazy[k] = R::upop(self.lazy[k], v); self.lazy_evaluate_node(k, height); return; } self.update_sub(a, b, v, 2 * k + 1, height - 1, l, (l + r) / 2); self.update_sub(a, b, v, 2 * k + 2, height - 1, (l + r) / 2, r); self.update_node(k); } /* ary[i] = upop(ary[i], v) for i in [a, b) (half-inclusive) */ #[inline] pub fn update(&mut self, a: usize, b: usize, v: R::U) { let n = self.n; let dep = self.dep; self.update_sub(a, b, v, 0, dep, 0, n); } /* l,r are for simplicity */ fn query_sub(&mut self, a: usize, b: usize, k: usize, height: usize, l: usize, r: usize) -> R::T { self.lazy_evaluate_node(k, height); // [a,b) and [l,r) intersect? if r <= a || b <= l {return R::e();} if a <= l && r <= b {return self.dat[k];} let vl = self.query_sub(a, b, 2 * k + 1, height - 1, l, (l + r) / 2); let vr = self.query_sub(a, b, 2 * k + 2, height - 1, (l + r) / 2, r); self.update_node(k); R::biop(vl, vr) } /* [a, b) (note: half-inclusive) */ #[inline] pub fn query(&mut self, a: usize, b: usize) -> R::T { let n = self.n; let dep = self.dep; self.query_sub(a, b, 0, dep, 0, n) } } enum AddMax {} impl ActionRing for AddMax { type T = i64; // data type U = i64; // action, a |-> x |-> a + x fn biop(x: Self::T, y: Self::T) -> Self::T { std::cmp::max(x, y) } fn update(x: Self::T, a: Self::U, _height: usize) -> Self::T { x + a } fn upop(fst: Self::U, snd: Self::U) -> Self::U { fst + snd } fn e() -> Self::T { -1 << 50 } fn upe() -> Self::U { // identity for upop 0 } } const INF: i64 = 1 << 50; fn main() { let n: usize = get(); let q: usize = get(); let mut a: Vec<i64> = (0..n).map(|_| get()).collect(); let mut acc = vec![0; n + 1]; for i in 0..n { acc[i + 1] = acc[i] + a[i]; } let mut stma = LazySegTree::<AddMax>::with(&acc); for i in 0..n + 1 { acc[i] = -acc[i]; } let mut stmi = LazySegTree::<AddMax>::with(&acc); let mut st = SegTree::new(n, |(mi1, ma1, v1, d1), (mi2, ma2, v2, d2)| { (min(mi1, d1 + mi2), max(ma1, d1 + ma2), max(v1, max(v2, d1 + ma2 - mi1)), d1 + d2) }, (INF, -INF, -INF, 0)); for i in 0..n { let x = a[i]; st.update(i, (0, x, x, x)); } for _ in 0..q { let kind = get_word(); if kind == "set" { let i: usize = get(); let x: i64 = get(); let diff = x - a[i - 1]; stma.update(i, n + 1, diff); stmi.update(i, n + 1, -diff); st.update(i - 1, (0, x, x, x)); a[i - 1] = x; } else { // TODO: don't assume l2 <= r2, l1 <= r1 let l1 = get::<usize>() - 1; let l2: usize = get(); let r1: usize = get(); let r2 = get::<usize>() + 1; let l2 = min(l2, r2 - 1); let r1 = max(r1, l1 + 1); let x = min(l2, r1); let y = max(l2, r1); // eprintln!("{} {} {} {} {} {}", l1, l2, r1, r2, x, y); let mut tmp = stma.query(r1, r2) + stmi.query(l1, x); tmp = max(tmp, stma.query(y, r2) + stmi.query(l1, l2)); if l2 > r1 { tmp = max(tmp, st.query(x, y).2); } println!("{}", tmp); } } }