AtCoder Beginner Contest 314 D

https://atcoder.jp/contests/abc314/tasks/abc314_d

1が続く間は、変えた位置を記録しておきます。2か3が出てくるとそれをリセットします。最後に、全体を大文字か小文字にしますが、記録していた位置だけは大文字、小文字を変えずにそのままにします。
Rustのバージョンが大幅にアップしましたね。手元と同じです。

// LOWER
#![allow(non_snake_case)]

use std::collections::HashSet;


//////////////////// 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()
}


//////////////////// Query ////////////////////

struct Query {
    t: i32,
    x: usize,
    c: char
}

impl Query {
    fn operate(&self, cs: &mut VecChar) {
        match *self {
            Query { t: 1, x, c } => cs.change(x-1, c),
            Query { t, x: _, c: _ } => cs.turn(t)
        }
    }
    
    fn read() -> Query {
        let v: Vec<String> = read_vec();
        let t: i32 = v[0].parse().unwrap();
        let x: usize = v[1].parse().unwrap();
        let c = v[2].chars().next().unwrap();
        Query { t, x, c }
    }
}


//////////////////// VecChar ////////////////////

struct VecChar {
    cs: Vec<char>,
    prev_t: i32,
    change_indices: HashSet<usize>
}

impl VecChar {
    fn new(S: String) -> VecChar {
        let cs: Vec<char> = S.chars().collect();
        let change_indices: HashSet<usize> = HashSet::new();
        VecChar { cs, prev_t: 1, change_indices }
    }
    
    fn change(&mut self, x: usize, c: char) {
        self.cs[x] = c;
        self.change_indices.insert(x);
    }
    
    fn turn(&mut self, t: i32) {
        self.prev_t = t;
        self.change_indices.clear()
    }
    
    fn convert(&self, i: usize) -> char {
        if self.change_indices.contains(&i) {
            self.cs[i]
        }
        else if self.prev_t == 2 {
            self.cs[i].to_ascii_lowercase()
        }
        else if self.prev_t == 3 {
            self.cs[i].to_ascii_uppercase()
        }
        else {
            self.cs[i]
        }
    }
    
    fn to_string(&self) -> String {
        (0..self.cs.len()).map(|i| self.convert(i)).collect::<String>()
    }
}


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

fn read_input() -> (String, usize) {
    let _N: usize = read();
    let S = read();
    let Q = read();
    (S, Q)
}

fn f(S: String, Q: usize) -> String {
    let mut cs = VecChar::new(S);
    for _ in 0..Q {
        let query = Query::read();
        query.operate(&mut cs)
    }
    cs.to_string()
}


//////////////////// main ////////////////////

fn main() {
    let (S, Q) = read_input();
    println!("{}", f(S, Q))
}