提出 #61465394
ソースコード 拡げる
fn main() {
input! {
n: usize, q: usize,
a: [Mint; n],
}
let mut list = a.into_iter().collect::<SplayTreeList::<RangeAffineRangeSum>>();
for _ in 0 .. q {
input!(t: usize);
if t == 0 {
input!(l: usize, r: usize, b: Mint, c: Mint);
list.apply_range(l .. r, (b, c));
} else {
input!(l: usize, r: usize);
println!("{}", list.prod(l .. r).0);
}
}
}
enum RangeAffineRangeSum {}
impl SplayTreeHelper for RangeAffineRangeSum {
type Value = Mint;
type Summary = (Mint, Mint);
type Action = (Mint, Mint);
fn value_map(&(b, c): &Self::Action, a: &mut Self::Value) {
*a = b * *a + c;
}
fn summarize(&a: &Self::Value) -> Self::Summary {
(a, Mint::from(1))
}
fn sum_empty() -> Self::Summary {
(Mint::from(0), Mint::from(0))
}
fn sum_concat(&(x1, n1): &Self::Summary, &(x2, n2): &Self::Summary) -> Self::Summary {
(x1 + x2, n1 + n2)
}
fn sum_map(&(b, c): &Self::Action, &(x, n): &Self::Summary) -> Self::Summary {
(b * x + c * n, n)
}
fn compose(&(b1, c1): &Self::Action, &(b2, c2): &Self::Action) -> Self::Action {
(b1 * b2, b1 * c2 + c1)
}
}
use ac_library::ModInt998244353 as Mint;
use proconio::input;
use splay_tree_list::{List as SplayTreeList, Helper as SplayTreeHelper};
pub mod splay_tree_list {
use std::{cell::UnsafeCell, iter::FromIterator, mem::replace, ops::RangeBounds};
pub trait Helper {
/// 要素
type Value;
/// 集約値
type Summary: Clone;
/// 作用
type Action: Clone;
/// 要素への作用
fn value_map(f: &Self::Action, x: &mut Self::Value) {
let _ = (f, x);
}
/// 要素の集約値
fn summarize(x: &Self::Value) -> Self::Summary;
/// 集約値の単位元(空のリストに対する集約値)
fn sum_empty() -> Self::Summary;
/// 集約値の連結
fn sum_concat(x: &Self::Summary, y: &Self::Summary) -> Self::Summary;
/// 左右反転したときの集約値(連結が非可換な場合に定義)
fn sum_rev(x: &Self::Summary) -> Self::Summary {
x.clone()
}
/// 集約値への作用
fn sum_map(f: &Self::Action, x: &Self::Summary) -> Self::Summary {
let _ = f;
x.clone()
}
/// 作用の合成(f∘g)
fn compose(f: &Self::Action, g: &Self::Action) -> Self::Action {
let _ = g;
f.clone()
}
}
pub struct List<H: Helper> {
root: UnsafeCell<Option<Box<Node<H>>>>,
}
impl<H: Helper> List<H> {
pub fn new() -> Self {
Self { root: UnsafeCell::new(None) }
}
pub fn is_empty(&self) -> bool {
unsafe { &*self.root.get() }.is_none()
}
pub fn len(&self) -> usize {
unsafe { &*self.root.get() }.as_ref().map(|root| root.len() ).unwrap_or(0)
}
pub fn front(&self) -> Option<&H::Value> {
if self.is_empty() {
None
} else {
Some(&self[0])
}
}
pub fn back(&self) -> Option<&H::Value> {
if self.is_empty() {
None
} else {
Some(&self[self.len() - 1])
}
}
pub fn set(&mut self, index: usize, value: H::Value) {
assert!(index < self.len());
let mut root = self.root.get_mut().take().unwrap();
root = root.set_value(index, value);
*self.root.get_mut() = Some(root);
}
pub fn reverse(&mut self) {
if let Some(root) = self.root.get_mut() {
root.reverse();
}
}
pub fn reverse_range(&mut self, range: impl RangeBounds<usize>) {
let (l, r) = self.range(range);
assert!(l <= r && r <= self.len());
let [left, mut mid, right] = Node::split3(self.root.get_mut().take(), l, r);
if let Some(node) = mid.as_mut() {
node.reverse();
}
*self.root.get_mut() = Node::merge3(left, mid, right);
}
pub fn rotate_left(&mut self, n: usize) {
assert!(n <= self.len());
let [mut left, mut right] = Node::split(self.root.get_mut().take(), n);
if let Some(left) = left.as_mut() {
left.reverse();
}
if let Some(right) = right.as_mut() {
right.reverse();
}
*self.root.get_mut() = Node::merge(left, right);
self.reverse();
}
pub fn rotate_right(&mut self, n: usize) {
assert!(n <= self.len());
self.rotate_left(self.len() - n);
}
pub fn swap(&mut self, i: usize, j: usize) {
assert!(i < self.len() && j < self.len());
if i == j {
return;
}
let (i, j) = (i.min(j), i.max(j));
let [rest, y, c] = Node::split3(self.root.get_mut().take(), j, j + 1);
let [a, x, b] = Node::split3(rest, i, i + 1);
*self.root.get_mut() = Node::merge3(Node::merge3(a, y, b), x, c);
}
pub fn append(&mut self, other: &mut Self) {
let root = Node::merge(self.root.get_mut().take(), other.root.get_mut().take());
*self.root.get_mut() = root;
}
pub fn split_off(&mut self, index: usize) -> Self {
let [root, other_root] = Node::split(self.root.get_mut().take(), index);
*self.root.get_mut() = root;
Self { root: UnsafeCell::new(other_root) }
}
pub fn insert(&mut self, index: usize, value: H::Value) {
assert!(index <= self.len());
let [before, after] = Node::split(self.root.get_mut().take(), index);
*self.root.get_mut() = Node::merge3(before, Some(Node::new(value)), after);
}
pub fn push_front(&mut self, value: H::Value) {
*self.root.get_mut() = Node::merge(Some(Node::<H>::new(value)), self.root.get_mut().take());
}
pub fn push_back(&mut self, value: H::Value) {
*self.root.get_mut() = Node::merge(self.root.get_mut().take(), Some(Node::<H>::new(value)));
}
pub fn pop_front(&mut self) -> Option<H::Value> {
if self.is_empty() {
None
} else {
let [node, rest] = Node::split(self.root.get_mut().take(), 1);
let value = Node::into_inner(node).pop();
*self.root.get_mut() = rest;
value
}
}
pub fn pop_back(&mut self) -> Option<H::Value> {
if self.is_empty() {
None
} else {
let index = self.len() - 1;
let [rest, node] = Node::split(self.root.get_mut().take(), index);
let value = Node::into_inner(node).pop();
*self.root.get_mut() = rest;
value
}
}
pub fn remove(&mut self, index: usize) -> Option<H::Value> {
if index < self.len() {
let [before, node, after] = Node::split3(self.root.get_mut().take(), index, index + 1);
let value = Node::into_inner(node).pop();
*self.root.get_mut() = Node::merge(before, after);
value
} else {
None
}
}
pub fn prod(&self, range: impl RangeBounds<usize>) -> H::Summary {
let (l, r) = self.range(range);
assert!(l <= r && r <= self.len());
let [left, mut mid, right] = Node::split3(unsafe { (&mut *self.root.get()).take() }, l, r);
let summary = mid.as_mut().map(|node| node.summary() ).unwrap_or_else(H::sum_empty);
unsafe {
*self.root.get() = Node::merge3(left, mid, right);
}
summary
}
pub fn apply_range(&mut self, range: impl RangeBounds<usize>, f: H::Action) {
let (l, r) = self.range(range);
assert!(l <= r && r <= self.len());
let [left, mut mid, right] = Node::split3(self.root.get_mut().take(), l, r);
if let Some(node) = mid.as_mut() {
node.apply(&f);
}
*self.root.get_mut() = Node::merge3(left, mid, right);
}
fn range(&self, range: impl RangeBounds<usize>) -> (usize, usize) {
use std::ops::Bound::*;
let l = match range.start_bound() { Included(&l) => l, Excluded(&l) => l + 1, Unbounded => 0 };
let r = match range.end_bound() { Excluded(&r) => r, Included(&r) => r + 1, Unbounded => self.len() };
(l, r)
}
}
impl<H: Helper> FromIterator<H::Value> for List<H> {
fn from_iter<T: IntoIterator<Item = H::Value>>(iter: T) -> Self {
Self { root: UnsafeCell::new(Node::<H>::from_iter(iter.into_iter())) }
}
}
impl<H: Helper> From<Vec<H::Value>> for List<H> {
fn from(value: Vec<H::Value>) -> Self {
Self::from_iter(value)
}
}
impl<H: Helper> std::ops::Index<usize> for List<H> {
type Output = H::Value;
fn index(&self, index: usize) -> &Self::Output {
assert!(index < self.len());
let root = unsafe { (&mut *self.root.get()).as_mut().unwrap_unchecked() };
root.value(index)
}
}
impl<H: Helper> IntoIterator for List<H> {
type IntoIter = <Vec<H::Value> as IntoIterator>::IntoIter;
type Item = H::Value;
fn into_iter(mut self) -> Self::IntoIter {
Node::into_inner(self.root.get_mut().take()).into_iter()
}
}
impl<H: Helper> std::fmt::Debug for List<H> where H::Value: std::fmt::Debug {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.len() {
0 => f.write_str("[]"),
1 => f.write_fmt(format_args!("[{:?}]", &self[0])),
_ => {
f.write_fmt(format_args!("[{:?}", &self[0]))?;
for i in 1 .. self.len() {
f.write_fmt(format_args!(", {:?}", &self[i]))?;
}
f.write_str("]")
}
}
}
}
pub struct Node<H: Helper> {
children: [Option<Box<Self>>; 2],
len: u32,
reversed: bool,
value: H::Value,
summary: H::Summary,
lazy: Option<H::Action>,
}
impl<H: Helper> std::fmt::Debug for Node<H> where H::Value: std::fmt::Debug, H::Summary: std::fmt::Debug, H::Action: std::fmt::Debug {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let lazy = self.lazy.as_ref().map(|lazy| format!(", lazy={:?}", lazy) ).unwrap_or_else(|| "".to_string() );
let reversed = if self.reversed { ", reversed" } else { "" };
f.write_fmt(format_args!("Node(len={}, value={:?}, summary={:?}{}{}) [{:?}, {:?}]", self.len, &self.value, &self.summary, lazy, reversed, &self.children[0], &self.children[1]))
}
}
impl<H: Helper> Node<H> {
pub fn new(value: H::Value) -> Box<Self> {
Box::new(Self {
children: [None, None],
len: 1,
reversed: false,
summary: H::summarize(&value),
value,
lazy: None,
})
}
pub fn from_iter(iter: impl Iterator<Item = H::Value>) -> Option<Box<Self>> {
let mut node = None;
for value in iter {
node = Self::merge(node, Some(Self::new(value)));
}
node
}
pub fn len(self: &Box<Self>) -> usize {
self.len as usize
}
pub fn into_inner(node: Option<Box<Self>>) -> Vec<H::Value> {
fn dfs<H: Helper>(node: Option<Box<Node<H>>>, values: &mut Vec<H::Value>) {
let Some(mut node) = node else { return };
node.push();
dfs(node.children[0].take(), values);
values.push(node.value);
dfs(node.children[1].take(), values);
}
let mut values = Vec::with_capacity(node.as_ref().map(|node| node.len() ).unwrap_or(0));
dfs(node, &mut values);
values
}
// update self.len, self.summary
fn update(&mut self) {
self.summary = H::summarize(&self.value);
self.len = 1;
if let Some(child) = &self.children[0] {
self.len += child.len;
self.summary = H::sum_concat(&child.summary, &self.summary);
}
if let Some(child) = &self.children[1] {
self.len += child.len;
self.summary = H::sum_concat(&self.summary, &child.summary);
}
}
// self.lazy, self.reversed の遅延を解消し、 self.value, self.children に反映する
fn push(&mut self) {
if let Some(lazy) = self.lazy.take() {
H::value_map(&lazy, &mut self.value);
for child in &mut self.children.iter_mut().filter_map(Option::as_mut) {
child.apply(&lazy);
}
}
if replace(&mut self.reversed, false) {
self.children.swap(0, 1);
for child in &mut self.children.iter_mut().filter_map(Option::as_mut) {
child.reverse();
}
}
}
pub fn apply(&mut self, f: &H::Action) {
if let Some(lazy) = &self.lazy {
self.lazy = Some(H::compose(f, lazy));
} else {
self.lazy = Some(f.clone());
}
self.summary = H::sum_map(f, &self.summary);
}
pub fn reverse(&mut self) {
self.reversed ^= true;
self.summary = H::sum_rev(&self.summary);
}
pub fn summary(&mut self) -> H::Summary {
self.push();
self.summary.clone()
}
fn rotate(mut self: Box<Self>, dir: bool) -> Box<Self> {
let Some(mut child) = self.children[dir as usize].take() else { return self };
self.children[dir as usize] = child.children[!dir as usize].take();
self.update();
child.children[!dir as usize] = Some(self);
child.update();
child
}
pub fn value<'a>(self: &'a mut Box<Self>, index: usize) -> &'a H::Value {
// Box をコピー(以降コピー元の値を参照してはいけない)
let mut node = unsafe { Box::from_raw((*self).as_mut() as *mut Self) };
node = node.splay(index);
node.push();
unsafe {
// write でコピー元の Box が破棄されることを回避
(self as *mut Box<Self>).write(node);
}
&self.value
}
pub fn set_value(self: Box<Self>, index: usize, value: H::Value) -> Box<Self> {
let mut node = self.splay(index);
node.push();
node.value = value;
node
}
pub fn splay(mut self: Box<Self>, mut index: usize) -> Box<Self> {
debug_assert!(index < self.len as usize);
self.push();
let left_len = self.children[0].as_ref().map(|child| child.len ).unwrap_or(0) as usize;
if index < left_len {
self.children[0] = self.children[0].take().map(|child| child.splay(index) );
self.update();
return self.rotate(false);
}
index -= left_len;
if index == 0 {
return self;
}
index -= 1;
self.children[1] = self.children[1].take().map(|child| child.splay(index) );
self.update();
self.rotate(true)
}
pub fn merge(left: Option<Box<Self>>, right: Option<Box<Self>>) -> Option<Box<Self>> {
let Some(mut right) = right else { return left };
right = right.splay(0);
right.push();
right.children[0] = left;
right.update();
Some(right)
}
pub fn split(node: Option<Box<Self>>, index: usize) -> [Option<Box<Self>>; 2] {
let Some(mut node) = node else { return [None, None] };
debug_assert!(index <= node.len as usize);
if index == node.len as usize {
return [Some(node), None];
}
node = node.splay(index);
node.push();
let left = node.children[0].take();
node.update();
[left, Some(node)]
}
pub fn split3(node: Option<Box<Self>>, l: usize, r: usize) -> [Option<Box<Self>>; 3] {
if l == 0 {
let [mid, right] = Self::split(node, r);
return [None, mid, right];
}
let Some(mut node) = node else { return [None, None, None] };
node = node.splay(l - 1);
node.push();
let [mid, right] = Self::split(node.children[1].take(), r - l);
node.update();
[Some(node), mid, right]
}
pub fn merge3(left: Option<Box<Self>>, mid: Option<Box<Self>>, right: Option<Box<Self>>) -> Option<Box<Self>> {
let rest = Self::merge(mid, right);
let Some(mut left) = left else { return rest };
left.push();
if left.children[1].is_none() {
left.children[1] = rest;
left.update();
Some(left)
} else {
Self::merge(Some(left), rest)
}
}
}
}
提出情報
ジャッジ結果
| セット名 |
Sample |
All |
| 得点 / 配点 |
0 / 0 |
100 / 100 |
| 結果 |
|
|
| セット名 |
テストケース |
| Sample |
example_00 |
| All |
example_00, max_random_00, max_random_01, max_random_02, random_00, random_01, random_02, small_00, small_01, small_02, small_03, small_04, small_05, small_06, small_07, small_08, small_09, small_random_00, small_random_01 |
| ケース名 |
結果 |
実行時間 |
メモリ |
| example_00 |
AC |
1 ms |
1948 KiB |
| max_random_00 |
AC |
1751 ms |
72756 KiB |
| max_random_01 |
AC |
1759 ms |
81924 KiB |
| max_random_02 |
AC |
1728 ms |
75092 KiB |
| random_00 |
AC |
1370 ms |
64840 KiB |
| random_01 |
AC |
1417 ms |
60736 KiB |
| random_02 |
AC |
784 ms |
17624 KiB |
| small_00 |
AC |
1 ms |
1960 KiB |
| small_01 |
AC |
1 ms |
1936 KiB |
| small_02 |
AC |
1 ms |
1928 KiB |
| small_03 |
AC |
1 ms |
1972 KiB |
| small_04 |
AC |
1 ms |
1960 KiB |
| small_05 |
AC |
1 ms |
1856 KiB |
| small_06 |
AC |
1 ms |
1968 KiB |
| small_07 |
AC |
1 ms |
1960 KiB |
| small_08 |
AC |
1 ms |
2056 KiB |
| small_09 |
AC |
1 ms |
1948 KiB |
| small_random_00 |
AC |
2 ms |
1972 KiB |
| small_random_01 |
AC |
2 ms |
1960 KiB |