以下の内容はhttps://inamori.hateblo.jp/entry/2025/08/31/195850より取得しました。


AtCoder Beginner Contest 421 D

https://atcoder.jp/contests/abc421/tasks/abc421_d

RLEが2人で違いますが、分割して同期を取ると簡単になります。
Generic版のPointを今までより強化しました。

// RLE Moving
#![allow(non_snake_case)]


//////////////////// library ////////////////////

fn read<T: std::str::FromStr>() -> T {
    let mut line = String::new();
    std::io::stdin().read_line(&mut line).ok();
    line.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>().split_whitespace()
            .map(|e| e.parse().ok().unwrap()).collect()
}


//////////////////// Point ////////////////////

use std::ops::{Add, Sub, Mul, Neg};

#[derive(Copy, Clone, PartialEq)]
struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn new(x: T, y: T) -> Self {
        Self { x, y }
    }
}

impl<T> Add<Point<T>> for Point<T>
where T: Add<Output = T> + Copy,
{
    type Output = Point<T>;
    
    fn add(self, other: Self) -> Self::Output {
        Self::new(self.x + other.x, self.y + other.y)
    }
}

impl<T> Sub<Point<T>> for Point<T>
where T: Sub<Output = T> + Copy,
{
    type Output = Point<T>;
    
    fn sub(self, other: Self) -> Self::Output {
        Self::new(self.x - other.x, self.y - other.y)
    }
}

// Point<T> * T
impl<T> Mul<T> for Point<T>
where T: Mul<Output = T> + Copy,
{
    type Output = Point<T>;
    
    fn mul(self, other: T) -> Self::Output {
        Self::new(self.x * other, self.y * other)
    }
}

// Point<T> * T
impl<T> Neg for Point<T>
where T: Neg<Output = T> + Copy,
{
    type Output = Point<T>;
    
    fn neg(self) -> Self::Output {
        Self::new(-self.x, -self.y)
    }
}


//////////////////// process ////////////////////

type RLE = (Point<i64>, i64);

fn read_RLE() -> RLE {
    let v: Vec<String> = read_vec();
    let A: i64 = v[1].parse().ok().unwrap();
    match v[0].as_str() {
        "U" => (Point::new(-1,  0), A),
        "D" => (Point::new( 1,  0), A),
        "L" => (Point::new( 0, -1), A),
        _   => (Point::new( 0,  1), A)
    }
}

fn read_input() -> (Point<i64>, Point<i64>, Vec<RLE>, Vec<RLE>) {
    let v: Vec<i64> = read_vec();
    let Pt0 = Point::new(v[0], v[1]);
    let Pa0 = Point::new(v[2], v[3]);
    let w: Vec<usize> = read_vec();
    let (M, L) = (w[1], w[2]);
    let RLEt: Vec<RLE> = (0..M).map(|_| read_RLE()).collect();
    let RLEa: Vec<RLE> = (0..L).map(|_| read_RLE()).collect();
    (Pt0, Pa0, RLEt, RLEa)
}

use std::cmp::{min, max};

fn integrate(rles1: Vec<RLE>,
                rles2: Vec<RLE>) -> Vec<(Point<i64>, Point<i64>, i64)> {
    let mut v: Vec<(Point<i64>, Point<i64>, i64)> = vec![];
    let mut k: usize = 0;
    let mut l: usize = 0;
    let L1 = rles1.len();
    let L2 = rles2.len();
    let mut acc1: i64 = 0;
    let mut acc2: i64 = 0;
    while k < L1 && l < L2 {
        let (dir1, n1) = rles1[k];
        let (dir2, n2) = rles2[l];
        if acc1 + n1 == acc2 + n2 {
            let m = min(n1, n2);
            v.push((dir1, dir2, m));
            k += 1;
            l += 1;
            acc1 += n1;
            acc2 += n2
        }
        else if acc1 + n1 > acc2 + n2 {
            v.push((dir1, dir2, acc2 + n2 - max(acc1, acc2)));
            l += 1;
            acc2 += n2
        }
        else {
            v.push((dir1, dir2, acc1 + n1 - max(acc1, acc2)));
            k += 1;
            acc1 += n1
        }
    }
    v
}

fn collides(pt1: Point<i64>, pt2: Point<i64>,
                dir1: Point<i64>, dir2: Point<i64>, n: i64) -> bool {
    let v = pt1 - pt2;
    let d = dir2 - dir1;
    if dir1 == dir2 || v.x * d.y != v.y * d.x {
        false
    }
    else {
        if v.x != 0 {
            if v.x % d.x != 0 {
                false
            }
            else {
                let m = v.x / d.x;
                0 < m && m <= n
            }
        }
        else {
            if v.y % d.y != 0 {
                false
            }
            else {
                let m = v.y / d.y;
                0 < m && m <= n
            }
        }
    }
}

fn num_crosses(pt1: Point<i64>, pt2: Point<i64>,
                dir1: Point<i64>, dir2: Point<i64>, n: i64) -> i64 {
    if pt1 == pt2 {
        if dir1 == dir2 {
            n
        }
        else {
            0
        }
    }
    else {
        if collides(pt1, pt2, dir1, dir2, n) {
            1
        }
        else {
            0
        }
    }
}

fn F(Pt0: Point<i64>, Pa0: Point<i64>, RLEt: Vec<RLE>, RLEa: Vec<RLE>) -> i64 {
    let v = integrate(RLEt, RLEa);
    let mut counter: i64 = 0;
    let mut pt1 = Pt0;
    let mut pt2 = Pa0;
    for (dir1, dir2, n) in v {
        counter += num_crosses(pt1, pt2, dir1, dir2, n);
        pt1 = pt1 + dir1 * n;
        pt2 = pt2 + dir2 * n;
    }
    counter
}

fn main() {
    let (Pt0, Pa0, RLEt, RLEa) = read_input();
    println!("{}", F(Pt0, Pa0, RLEt, RLEa))
}



以上の内容はhttps://inamori.hateblo.jp/entry/2025/08/31/195850より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14