🤖

AtCoder Beginner Contest 329振り返り

2023/11/19に公開

A - Spread

JOINを使えばよい

use itertools::Itertools;
use proconio::{input, marker::Chars};

fn main() {
    input! {
        s: Chars,
    }

    let str = s.iter().join(" ");
    println!("{}", str);
}

実はそのまま出力してもいい。

fn main() {
    input! {
        s: Chars,
    }

    for c in s.iter() {
        println!("{}", c);
    }
}

B - Next

最初に最大値を取得し、それを取り除いて最大値を検索する。

use proconio::input;

fn main() {
    input! {
        n: usize,
        a: [usize; n],
    }

    let max = *a.iter().max().unwrap();
    let ans = a.iter().filter(|&&x| x != max).max().unwrap();
    println!("{}", ans);
}

C - Count xxx

違う文字が見つかるまで右に検索していく。
違う文字が見つかったらそれを記録する。

use std::collections::BTreeSet;

use proconio::{input, marker::Chars};

fn main() {
    input! {
        n: usize,
        s: Chars,
    }

    #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
    struct K {
        c: char,
        len: usize,
    }

    let mut memo: BTreeSet<K> = BTreeSet::new();

    let mut l = 0;
    for r in 0..n {
        if s[l] != s[r] {
            l = r;
        }
        let len = r - l + 1;
        memo.insert(K { c: s[l], len });
    }
    println!("{}", memo.len());
}

D - Election Quick Report

「候補者→投票数」のマップと「投票数→最小番号の候補者」のマップを作っておく。

ここまでしか解けなかった。

use std::collections::BTreeMap;

use proconio::{input, marker::Usize1};

fn main() {
    input! {
        n: usize,
        m: usize,
        a: [Usize1; m],
    }

    let mut voted = vec![0; n];
    let mut min_idx: BTreeMap<usize, usize> = BTreeMap::new();

    let mut max_v = 0;
    let mut max_i = a[0];

    for i in a.into_iter() {
        let v = voted[i] + 1;
        voted[i] = v;

        // 最小点数更新
        if let Some(&j) = min_idx.get(&v) {
            let m = i.min(j);
            min_idx.insert(v, m);
        } else {
            min_idx.insert(v, i);
        }

        if v >= max_v {
            // 順位が変わるかも?
            if max_v == v {
                // 同点
                if let Some(&j) = min_idx.get(&v) {
                    // 既に点数あるひとがいる
                    max_i = i.min(j);
                    max_v = v;
                } else {
                    max_i = i;
                    max_v = v;
                }
            } else {
                // 最高得点を記録
                max_v = v;
                max_i = i;
            }
        }

        println!("{}", max_i + 1);
    }
}

E - Stamp

スタンプをおせるだけおしていく。隣接するところにもスタンプをおす。
解説見て後から実装したがこれ実装するのは結構しんどい。
速めに見切りをつけるべきだった。

use proconio::{
    input,
    marker::Chars,
};

fn main() {
    input! {
        n: usize,
        m: usize,
        mut s: Chars,
        t: Chars,
    }

    let mut stack: Vec<usize> = Vec::new();

    let mut cnt = 0;
    for i in 0..(n - m + 1) {
        stack.push(i);
    }

    while let Some(i) = stack.pop() {
        if cnt == n {
            println!("Yes");
            return;
        }

        if !(0..m).all(|j| t[j] == s[i + j] || '?' == s[i + j]) {
            // スタンプをおせない
            continue;
        }

        // スタンプをおす
        let mut stamped = false;
        for j in 0..m {
            if s[i + j] != '?' {
                s[i + j] = '?';
                cnt += 1;
                stamped = true;
            }
        }

        // スタンプを推す意味がない
        if !stamped {
            continue;
        }

        for j in -(m as i64)..=(m as i64) {
            let i = (i as i64) + j;
            if i < 0 || i as usize + m > n {
                continue;
            }
            stack.push(i as usize);
        }
    }

    println!("No");
}

F - Colored Ball

順位表からE問題よりF問題を解いてる人が多かったので見切りをつけてF問題へ。
ナイーブな実装でTLEを起こして先にすすめず。
少ないほうから多いほうへコピーすれば計算量を減らせる。

これは所有権があるRustだとremoveしてinsertするだけで十分間に合う。

use std::collections::BTreeMap;

use proconio::{input, marker::Usize1};

fn main() {
    input! {
        n: usize,
        q: usize,
        c: [Usize1; n],
        queries: [(Usize1, Usize1); q]

    }

    let mut boxes = BTreeMap::new();
    for i in 0..n {
        let mut b = BTreeMap::new();
        b.insert(c[i], 1);
        boxes.insert(i, b);
    }

    for (a, b) in queries {
        let mut x = boxes.remove(&a).unwrap();
        let mut y = boxes.remove(&b).unwrap();

        if x.len() <= y.len() {
            for (k, cnt) in x {
                *y.entry(k).or_insert(0) += cnt;
            }
            println!("{}", y.keys().len());
            boxes.insert(a, BTreeMap::new());
            boxes.insert(b, y);
        } else {
            for (k, cnt) in y {
                *x.entry(k).or_insert(0) += cnt;
            }
            println!("{}", x.keys().len());
            boxes.insert(a, BTreeMap::new());
            boxes.insert(b, x);
        };
    }
}

総括

E問題を速めに見切るスキルとD問題をささっと解ければもっとパフォーマンスでてたかなぁ。
レーティング変動なし。

Discussion