AtCoder Beginner Contest 364

AtCoder Beginner Contest 364 です。

A - Glutton Takahashi

問題文

連続して “sweet” が2回出現しないようにする問題。最後の2つが “sweet” なら OK。

n = gets.to_i
s = n.times.map { gets.chomp }

ans = true

(n - 1).times do |i|
  ans  &= !(s[i] == "sweet" && s[i + 1] == "sweet") || (i + 1 == n - 1)
end

puts ans ? "Yes" : "No"

提出



B - Grid Walk

問題文

指示に従って移動して、壁にぶつかったらそこで止まる。最後の位置を出力する感じ。

fn main() {
    input! {
        h : usize,
        w : usize,
        mut s : (Usize1, Usize1),
        c : [Chars; h],
        x : Chars
    }

    for &x in x.iter() {
        match x {
            'L' => {
                if s.1>0 && c[s.0][s.1 - 1] != '#' { s.1 -= 1; }
            }
            'R' => {
                if s.1+1<w && c[s.0][s.1 + 1] != '#' { s.1 += 1; }
            }
            'U' => {
                if s.0>0 && c[s.0 - 1][s.1] != '#' { s.0 -= 1; }
            }
            'D' => {
                if s.0+1<h && c[s.0 + 1][s.1] != '#' { s.0 += 1; }
            }
            _ => unreachable!()
        }
    }

    println!("{} {}", s.0 + 1, s.1 + 1);
}

提出



C - Minimum Glutton

問題文

(a[i], b[i]) のペアでソートして、それぞれの条件を満たす最小の数を求める。

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

    let index = (0..n).sorted_by_key(|&i| (a[i], b[i])).collect_vec();
    let mut ans = n;

    {
        let mut sum = 0;
        for (i, &j) in index.iter().rev().enumerate() {
            sum += a[j];
            if sum > x { ans = ans.min(i + 1); }
        }
    }

    let index = (0..n).sorted_by_key(|&i| (b[i], a[i])).collect_vec();
    {
        let mut sum = 0;
        for (i, &j) in index.iter().rev().enumerate() {
            sum += b[j];
            if sum > y { ans = ans.min(i + 1); }
        }
    }

    println!("{}", ans);
}

提出



D - K-th Nearest

問題文

二分探索で条件を満たす最小の範囲を求める。

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

    a.sort();

    let mut ans = Vec::with_capacity(q);
    for &(b, c) in &queries {
        if c == n {
            ans.push((a[0]-b).abs().max((a[n-1]-b).abs()));
            continue
        }

        let mut l = -1;
        let mut r = 3_000_000_000;
        while l + 1 < r {
            let m = (l + r) / 2;
            let left = a.lower_bound(&(b - m));
            let right = a.upper_bound(&(b + m));
            if right - left + 1 > c { r = m; }
            else { l = m; }
        }

        ans.push(r);
    }

    println!("{}", ans.iter().join("\n"));
}

提出



E - Maximum Glutton

問題文

D問題沼って時間がかかったとはいえ、瞬殺できるべき問題だった。結局本番中には解けず。 DPするんだけど、 X,Y をキーに持っては TLE するので、 X と何個使ったかをキーに持って、Yが条件を満たす最大の個数を求める。

fn main() {
    input! {
        n : usize,
        x : usize,
        y : usize,
        ab : [(usize, usize); n]
    }

    let ab = ab.into_iter().filter(|&(a, b)| a <= x && b <= y).collect_vec();

    let mut dp = vec![vec![usize::MAX >> 5; x + 1]; n + 1];
    dp[0][0] = 0;

    for &(a, b) in ab.iter() {
        for i in (0..n).rev() {
            for j in 0..=x.saturating_sub(a) {
                if dp[i][j] + b > y { continue; }
                dp[i + 1][j + a] = dp[i + 1][j + a].min(dp[i][j] + b);
            }
        }
    }

    let mut ans = 0;
    for i in 0..=n {
        for j in 0..=x {
            if dp[i][j] > y { continue; }
            let t = i + if i + 1 <= n { 1 } else { 0 };
            ans = ans.max(t);
        }
    }


    println!("{}", ans);
}

提出



F - Range Connect MST

問題文

見てない



G - Last Major City

問題文

見てない



まとめ

思考力さんが行方不明でした。E問題は瞬殺できるべきですねぇ…。 D問題も二分探索して答え求まってるのに、変なことしてたし。

パフォーマンス 1178。レート 1662 → 1621