結果

問題 No.449 ゆきこーだーの雨と雪 (4)
ユーザー ngtkanangtkana
提出日時 2023-10-06 19:43:24
言語 Rust
(1.77.0 + proconio)
結果
AC  
実行時間 331 ms / 5,000 ms
コード長 19,772 bytes
コンパイル時間 13,979 ms
コンパイル使用メモリ 401,584 KB
実行使用メモリ 20,864 KB
最終ジャッジ日時 2024-07-26 15:33:14
合計ジャッジ時間 24,917 ms
ジャッジサーバーID
(参考情報)
judge5 / judge3
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
6,812 KB
testcase_01 AC 1 ms
6,944 KB
testcase_02 AC 1 ms
6,940 KB
testcase_03 AC 3 ms
6,944 KB
testcase_04 AC 2 ms
6,944 KB
testcase_05 AC 3 ms
6,944 KB
testcase_06 AC 3 ms
6,944 KB
testcase_07 AC 2 ms
6,940 KB
testcase_08 AC 2 ms
6,940 KB
testcase_09 AC 2 ms
6,940 KB
testcase_10 AC 3 ms
6,940 KB
testcase_11 AC 2 ms
6,940 KB
testcase_12 AC 271 ms
16,828 KB
testcase_13 AC 319 ms
19,132 KB
testcase_14 AC 278 ms
19,264 KB
testcase_15 AC 331 ms
19,200 KB
testcase_16 AC 303 ms
19,020 KB
testcase_17 AC 301 ms
19,092 KB
testcase_18 AC 269 ms
16,828 KB
testcase_19 AC 276 ms
19,208 KB
testcase_20 AC 275 ms
19,016 KB
testcase_21 AC 313 ms
19,020 KB
testcase_22 AC 316 ms
19,120 KB
testcase_23 AC 266 ms
16,832 KB
testcase_24 AC 303 ms
19,080 KB
testcase_25 AC 255 ms
16,784 KB
testcase_26 AC 235 ms
16,760 KB
testcase_27 AC 310 ms
19,128 KB
testcase_28 AC 313 ms
19,196 KB
testcase_29 AC 282 ms
19,024 KB
testcase_30 AC 330 ms
19,220 KB
testcase_31 AC 317 ms
19,132 KB
testcase_32 AC 266 ms
19,136 KB
testcase_33 AC 288 ms
19,136 KB
testcase_34 AC 259 ms
16,860 KB
testcase_35 AC 319 ms
19,068 KB
testcase_36 AC 262 ms
16,856 KB
testcase_37 AC 223 ms
20,732 KB
testcase_38 AC 219 ms
19,132 KB
testcase_39 AC 193 ms
19,132 KB
testcase_40 AC 188 ms
19,260 KB
testcase_41 AC 221 ms
19,136 KB
testcase_42 AC 211 ms
19,264 KB
testcase_43 AC 175 ms
16,984 KB
testcase_44 AC 136 ms
16,860 KB
testcase_45 AC 160 ms
20,864 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

use crate::avl_tree::AvlTree;
use input::input;
use input::input_array;
use std::cmp::Reverse;
use std::collections::HashMap;
use std::iter::repeat;
use std::iter::repeat_with;

fn main() {
    let _ = input::<usize>();
    let allot = input::<String>()
        .split_whitespace()
        .map(|s| s.parse::<u64>().unwrap() * 50)
        .collect::<Vec<_>>();
    let (person_count, queries) = {
        let q = input::<usize>();
        let queries = repeat_with(|| input_array::<String, 2>())
            .take(q)
            .collect::<Vec<_>>();
        let mut names = queries
            .iter()
            .map(|query| query[0].as_str())
            .collect::<Vec<_>>();
        names.sort();
        names.dedup();
        let mut name_to_index = HashMap::new();
        for (i, &name) in names.iter().enumerate() {
            name_to_index.insert(name, i);
        }
        (
            names.len(),
            queries
                .iter()
                .map(|query| {
                    let name_index = name_to_index[query[0].as_str()];
                    match query[1].chars().next().unwrap() {
                        '?' => (name_index, Query::WhatRank),
                        pid => (name_index, Query::Solve((pid as u8 - b'A') as usize)),
                    }
                })
                .collect::<Vec<_>>(),
        )
    };

    let mut scores = vec![(0, Reverse(0)); person_count];
    let mut solved = vec![0; allot.len()];
    let mut sorted = repeat((0, Reverse(0)))
        .take(person_count)
        .collect::<AvlTree<_>>();
    for (time, &(person, query)) in queries.iter().enumerate() {
        match query {
            Query::WhatRank => {
                let rank = sorted.binary_search(&scores[person]).unwrap();
                let ans = person_count - rank;
                println!("{}", ans);
            }
            Query::Solve(pid) => {
                sorted.remove(sorted.binary_search(&scores[person]).unwrap());
                scores[person].0 += allot[pid] + allot[pid] * 5 / (5 + solved[pid]);
                scores[person].1 .0 = time;
                sorted.insert(sorted.lower_bound(&scores[person]), scores[person]);
                solved[pid] += 1;
            }
        }
    }
}

#[derive(Debug, Clone, Copy)]
enum Query {
    Solve(usize),
    WhatRank,
}

// input {{{
#[allow(dead_code)]
mod input {
    use std::cell::Cell;
    use std::convert::TryFrom;
    use std::io::stdin;
    use std::io::BufRead;
    use std::io::BufReader;
    use std::io::Lines;
    use std::io::Stdin;
    use std::str::FromStr;
    use std::sync::Mutex;
    use std::sync::Once;
    type Server = Mutex<Lines<BufReader<Stdin>>>;
    static ONCE: Once = Once::new();
    pub struct Lazy(Cell<Option<Server>>);
    unsafe impl Sync for Lazy {}
    pub fn line() -> String {
        static SYNCER: Lazy = Lazy(Cell::new(None));
        ONCE.call_once(|| {
            SYNCER
                .0
                .set(Some(Mutex::new(BufReader::new(stdin()).lines())));
        });
        unsafe {
            (*SYNCER.0.as_ptr())
                .as_ref()
                .unwrap()
                .lock()
                .unwrap()
                .next()
                .unwrap()
                .unwrap()
        }
    }
    pub trait ForceFromStr: FromStr {
        fn force_from_str(s: &str) -> Self;
    }
    impl<T, E> ForceFromStr for T
    where
        T: FromStr<Err = E>,
        E: std::fmt::Debug,
    {
        fn force_from_str(s: &str) -> Self { s.parse().unwrap() }
    }
    pub fn input_array<T: ForceFromStr, const N: usize>() -> [T; N]
    where
        T: std::fmt::Debug,
    {
        <[_; N]>::try_from(input_vec()).unwrap()
    }
    pub fn input_vec<T: ForceFromStr>() -> Vec<T> {
        line()
            .split_whitespace()
            .map(T::force_from_str)
            .collect::<Vec<_>>()
    }
    pub fn input<T: ForceFromStr>() -> T { T::force_from_str(&line()) }
}
// }}}
// avl_tree {{{
#[allow(dead_code)]
mod avl_tree {
    #![allow(clippy::unnecessary_box_returns)]
    use std::borrow::Borrow;
    use std::cmp::Ordering;
    use std::fmt::Debug;
    use std::hash::Hash;
    use std::iter::successors;
    use std::iter::FromIterator;
    use std::mem::swap;
    use std::ops::Index;
    #[derive(Clone)]
    pub struct AvlTree<T> {
        root: Option<Box<Node<T>>>,
    }
    impl<T> AvlTree<T> {
        pub fn new() -> Self { Self::default() }

        pub fn is_empty(&self) -> bool { self.root.is_none() }

        pub fn len(&self) -> usize { len(self.root.as_deref()) }

        pub fn push_back(&mut self, value: T) {
            self.append(&mut Self {
                root: Some(new(value)),
            })
        }

        pub fn push_front(&mut self, value: T) {
            let mut swp = Self {
                root: Some(new(value)),
            };
            swp.append(self);
            *self = swp;
        }

        pub fn pop_back(&mut self) -> Option<T> {
            let root = self.root.take()?;
            let last_index = root.len - 1;
            let (left, center, _right) = split_delete(root, last_index);
            self.root = left;
            Some(center.value)
        }

        pub fn pop_front(&mut self) -> Option<T> {
            let (_left, center, right) = split_delete(self.root.take()?, 0);
            self.root = right;
            Some(center.value)
        }

        pub fn back(&self) -> Option<&T> { self.get(self.len().checked_sub(1)?) }

        pub fn front(&self) -> Option<&T> { self.get(0) }

        pub fn back_mut(&mut self) -> Option<&mut T> { self.get_mut(self.len().checked_sub(1)?) }

        pub fn front_mut(&mut self) -> Option<&mut T> { self.get_mut(0) }

        pub fn append(&mut self, other: &mut Self) {
            self.root = merge(self.root.take(), other.root.take());
        }

        pub fn split_off(&mut self, index: usize) -> Self {
            assert!(index <= self.len());
            let (left, right) = split(self.root.take(), index);
            self.root = left;
            Self { root: right }
        }

        pub fn insert(&mut self, index: usize, value: T) {
            assert!(index <= self.len());
            let other = self.split_off(index);
            self.root = Some(merge_with_root(self.root.take(), new(value), other.root));
        }

        pub fn remove(&mut self, index: usize) -> Option<T> {
            if index < self.len() {
                let (left, center, right) = split_delete(self.root.take().unwrap(), index);
                self.root = merge(left, right);
                Some(center.value)
            } else {
                None
            }
        }

        pub fn get(&self, index: usize) -> Option<&T> {
            if index < self.len() {
                Some(&get(self.root.as_ref().unwrap(), index).value)
            } else {
                None
            }
        }

        pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
            if index < self.len() {
                Some(&mut get_mut(self.root.as_mut().unwrap(), index).value)
            } else {
                None
            }
        }

        pub fn binary_search_by(&self, f: impl FnMut(&T) -> Ordering) -> Result<usize, usize> {
            binary_search_by(self.root.as_deref(), f)
        }

        pub fn binary_search_by_key<B: Ord>(
            &self,
            b: &B,
            mut f: impl FnMut(&T) -> B,
        ) -> Result<usize, usize> {
            self.binary_search_by(|x| f(x).cmp(b))
        }

        pub fn binary_search<Q: Ord>(&self, value: &Q) -> Result<usize, usize>
        where
            T: Borrow<Q>,
        {
            self.binary_search_by(|x| x.borrow().cmp(value))
        }

        pub fn partition_point(&self, mut is_right: impl FnMut(&T) -> bool) -> usize {
            partition_point(self.root.as_deref(), |node| is_right(&node.value))
        }

        pub fn lower_bound<Q: Ord>(&self, value: &Q) -> usize
        where
            T: Borrow<Q>,
        {
            partition_point(self.root.as_deref(), |node| value <= node.value.borrow())
        }

        pub fn upper_bound<Q: Ord>(&self, value: &Q) -> usize
        where
            T: Borrow<Q>,
        {
            partition_point(self.root.as_deref(), |node| value < node.value.borrow())
        }

        pub fn iter(&self) -> Iter<'_, T> {
            Iter {
                stack: successors(self.root.as_deref(), |current| current.left.as_deref())
                    .collect(),
                rstack: successors(self.root.as_deref(), |current| current.right.as_deref())
                    .collect(),
            }
        }
    }
    impl<T> Default for AvlTree<T> {
        fn default() -> Self { Self { root: None } }
    }
    impl<T: PartialEq> PartialEq for AvlTree<T> {
        fn eq(&self, other: &Self) -> bool { self.iter().eq(other) }
    }
    impl<T: PartialEq, A> PartialEq<[A]> for AvlTree<T>
    where
        T: PartialEq<A>,
    {
        fn eq(&self, other: &[A]) -> bool { self.iter().eq(other) }
    }
    impl<T: Eq> Eq for AvlTree<T> {}
    impl<T: PartialOrd> PartialOrd for AvlTree<T> {
        fn partial_cmp(&self, other: &Self) -> Option<Ordering> { self.iter().partial_cmp(other) }
    }
    impl<T: Ord> Ord for AvlTree<T> {
        fn cmp(&self, other: &Self) -> Ordering { self.iter().cmp(other) }
    }
    impl<T: Debug> Debug for AvlTree<T> {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            f.debug_list().entries(self).finish()
        }
    }
    impl<T: Hash> Hash for AvlTree<T> {
        fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
            self.iter().for_each(|elm| elm.hash(state));
        }
    }
    impl<T> IntoIterator for AvlTree<T> {
        type IntoIter = IntoIter<T>;
        type Item = T;

        fn into_iter(self) -> Self::IntoIter {
            let mut stack = Vec::new();
            if let Some(mut current) = self.root {
                while let Some(next) = current.left.take() {
                    stack.push(current);
                    current = next;
                }
                stack.push(current);
            }
            IntoIter { stack }
        }
    }
    impl<'a, T> IntoIterator for &'a AvlTree<T> {
        type IntoIter = Iter<'a, T>;
        type Item = &'a T;

        fn into_iter(self) -> Self::IntoIter { self.iter() }
    }
    impl<T> Index<usize> for AvlTree<T> {
        type Output = T;

        fn index(&self, index: usize) -> &Self::Output { self.get(index).unwrap() }
    }
    impl<T> FromIterator<T> for AvlTree<T> {
        fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
            fn from_slice_of_nodes<T>(nodes: &mut [Option<Box<Node<T>>>]) -> Option<Box<Node<T>>> {
                if nodes.is_empty() {
                    None
                } else {
                    let i = nodes.len() / 2;
                    Some(merge_with_root(
                        from_slice_of_nodes(&mut nodes[..i]),
                        nodes[i].take().unwrap(),
                        from_slice_of_nodes(&mut nodes[i + 1..]),
                    ))
                }
            }
            Self {
                root: from_slice_of_nodes(
                    iter.into_iter()
                        .map(new)
                        .map(Some)
                        .collect::<Vec<_>>()
                        .as_mut_slice(),
                ),
            }
        }
    }
    pub struct Iter<'a, T> {
        stack: Vec<&'a Node<T>>,
        rstack: Vec<&'a Node<T>>,
    }
    impl<'a, T> Iterator for Iter<'a, T> {
        type Item = &'a T;

        fn next(&mut self) -> Option<Self::Item> {
            let current = self.stack.pop()?;
            self.stack
                .extend(successors(current.right.as_deref(), |node| {
                    node.left.as_deref()
                }));
            if std::ptr::eq(current, *self.rstack.last().unwrap()) {
                self.stack.clear();
                self.rstack.clear();
            }
            Some(&current.value)
        }
    }
    impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
        fn next_back(&mut self) -> Option<Self::Item> {
            let current = self.rstack.pop()?;
            self.rstack
                .extend(successors(current.left.as_deref(), |node| {
                    node.right.as_deref()
                }));
            if std::ptr::eq(current, *self.stack.last().unwrap()) {
                self.stack.clear();
                self.rstack.clear();
            }
            Some(&current.value)
        }
    }
    pub struct IntoIter<T> {
        stack: Vec<Box<Node<T>>>,
    }
    impl<T> Iterator for IntoIter<T> {
        type Item = T;

        fn next(&mut self) -> Option<Self::Item> {
            let mut current = self.stack.pop()?;
            if let Some(mut current) = current.right.take() {
                while let Some(next) = current.left.take() {
                    self.stack.push(current);
                    current = next;
                }
                self.stack.push(current);
            }
            Some(current.value)
        }
    }
    #[derive(Clone)]
    struct Node<T> {
        left: Option<Box<Self>>,
        right: Option<Box<Self>>,
        value: T,
        len: usize,
        ht: u8,
    }
    fn new<T>(value: T) -> Box<Node<T>> {
        Box::new(Node {
            left: None,
            right: None,
            value,
            len: 1,
            ht: 1,
        })
    }
    impl<T> Node<T> {
        fn update(&mut self) {
            self.len = len(self.left.as_deref()) + 1 + len(self.right.as_deref());
            self.ht = 1 + ht(self.left.as_deref()).max(ht(self.right.as_deref()));
        }
    }
    fn len<T>(tree: Option<&Node<T>>) -> usize { tree.as_ref().map_or(0, |node| node.len) }
    fn ht<T>(tree: Option<&Node<T>>) -> u8 { tree.as_ref().map_or(0, |node| node.ht) }
    fn balance<T>(node: &mut Box<Node<T>>) {
        fn rotate_left<T>(node: &mut Box<Node<T>>) {
            let mut x = node.left.take().unwrap();
            let y = x.right.take();
            swap(node, &mut x);
            x.left = y;
            x.update();
            node.right = Some(x);
            node.update();
        }
        fn rotate_right<T>(node: &mut Box<Node<T>>) {
            let mut x = node.right.take().unwrap();
            let y = x.left.take();
            swap(node, &mut x);
            x.right = y;
            x.update();
            node.left = Some(x);
            node.update();
        }
        if ht(node.left.as_deref()) > 1 + ht(node.right.as_deref()) {
            let left = node.left.as_mut().unwrap();
            if ht(left.left.as_deref()) < ht(left.right.as_deref()) {
                rotate_right(left);
            }
            rotate_left(node);
        } else if ht(node.left.as_deref()) + 1 < ht(node.right.as_deref()) {
            let right = node.right.as_mut().unwrap();
            if ht(right.left.as_deref()) > ht(right.right.as_deref()) {
                rotate_left(right);
            }
            rotate_right(node);
        } else {
            node.update();
        }
    }
    fn merge_with_root<T>(
        mut left: Option<Box<Node<T>>>,
        mut center: Box<Node<T>>,
        mut right: Option<Box<Node<T>>>,
    ) -> Box<Node<T>> {
        match ht(left.as_deref()).cmp(&ht(right.as_deref())) {
            Ordering::Less => {
                let mut root = right.take().unwrap();
                root.left = Some(merge_with_root(left, center, root.left.take()));
                balance(&mut root);
                root
            }
            Ordering::Equal => {
                center.left = left;
                center.right = right;
                center.update();
                center
            }
            Ordering::Greater => {
                let mut root = left.take().unwrap();
                root.right = Some(merge_with_root(root.right.take(), center, right));
                balance(&mut root);
                root
            }
        }
    }
    fn merge<T>(
        left: Option<Box<Node<T>>>,
        mut right: Option<Box<Node<T>>>,
    ) -> Option<Box<Node<T>>> {
        match right.take() {
            None => left,
            Some(right) => {
                let (_none, center, rhs) = split_delete(right, 0);
                Some(merge_with_root(left, center, rhs))
            }
        }
    }
    #[allow(clippy::type_complexity)]
    fn split_delete<T>(
        mut root: Box<Node<T>>,
        index: usize,
    ) -> (Option<Box<Node<T>>>, Box<Node<T>>, Option<Box<Node<T>>>) {
        debug_assert!((0..root.len).contains(&index));
        let left = root.left.take();
        let right = root.right.take();
        let lsize = len(left.as_deref());
        match lsize.cmp(&index) {
            Ordering::Less => {
                let mut res = split_delete(right.unwrap(), index - lsize - 1);
                res.0 = Some(merge_with_root(left, root, res.0));
                res
            }
            Ordering::Equal => (left, root, right),
            Ordering::Greater => {
                let mut res = split_delete(left.unwrap(), index);
                res.2 = Some(merge_with_root(res.2, root, right));
                res
            }
        }
    }
    #[allow(clippy::type_complexity)]
    fn split<T>(
        tree: Option<Box<Node<T>>>,
        index: usize,
    ) -> (Option<Box<Node<T>>>, Option<Box<Node<T>>>) {
        match tree {
            Some(root) => {
                if root.len == index {
                    (Some(root), None)
                } else {
                    let (left, center, right) = split_delete(root, index);
                    (left, Some(merge_with_root(None, center, right)))
                }
            }
            None => (None, None),
        }
    }
    fn binary_search_by<T>(
        tree: Option<&Node<T>>,
        mut f: impl FnMut(&T) -> Ordering,
    ) -> Result<usize, usize> {
        let node = match tree {
            None => return Err(0),
            Some(node) => node,
        };
        let lsize = len(node.left.as_deref());
        match f(&node.value) {
            Ordering::Less => binary_search_by(node.right.as_deref(), f)
                .map(|index| lsize + 1 + index)
                .map_err(|index| lsize + 1 + index),
            Ordering::Equal => Ok(lsize),
            Ordering::Greater => binary_search_by(node.left.as_deref(), f),
        }
    }
    fn partition_point<T>(
        tree: Option<&Node<T>>,
        mut is_right: impl FnMut(&Node<T>) -> bool,
    ) -> usize {
        let node = match tree {
            None => return 0,
            Some(node) => node,
        };
        let lsize = len(node.left.as_deref());
        if is_right(node) {
            partition_point(node.left.as_deref(), is_right)
        } else {
            lsize + 1 + partition_point(node.right.as_deref(), is_right)
        }
    }
    fn get<T>(node: &Node<T>, index: usize) -> &Node<T> {
        let lsize = len(node.left.as_deref());
        match lsize.cmp(&index) {
            Ordering::Less => get(node.right.as_ref().unwrap(), index - lsize - 1),
            Ordering::Equal => node,
            Ordering::Greater => get(node.left.as_ref().unwrap(), index),
        }
    }
    fn get_mut<T>(node: &mut Node<T>, index: usize) -> &mut Node<T> {
        let lsize = len(node.left.as_deref());
        match lsize.cmp(&index) {
            Ordering::Less => get_mut(node.right.as_mut().unwrap(), index - lsize - 1),
            Ordering::Equal => node,
            Ordering::Greater => get_mut(node.left.as_mut().unwrap(), index),
        }
    }
}
// }}}
0