Problem:
Score : 200 points

Problem Statement

There are N participants in the CODE FESTIVAL 2016 Qualification contests. The participants are either students in Japan, students from overseas, or neither of these.

Only Japanese students or overseas students can pass the Qualification contests. The students pass when they satisfy the conditions listed below, from the top rank down. Participants who are not students cannot pass the Qualification contests.

A Japanese student passes the Qualification contests if the number of the participants who have already definitively passed is currently fewer than A+B.

An overseas student passes the Qualification contests if the number of the participants who have already definitively passed is currently fewer than A+B and the student ranks B-th or above among all overseas students.

A string S is assigned indicating attributes of all participants. If the i-th character of string S is a, this means the participant ranked i-th in the Qualification contests is a Japanese student; b means the participant ranked i-th is an overseas student; and c means the participant ranked i-th is neither of these.

Write a program that outputs for all the participants in descending rank either Yes if they passed the Qualification contests or No if they did not pass.

Constraints

1≦N,A,B≦100000

A+B≦N

S is N characters long.

S consists only of the letters a, b and c.

Input

Inputs are provided from Standard Input in the following form.

N A B
S

Output

Output N lines. On the i-th line, output Yes if the i-th participant passed the Qualification contests or No if that participant did not pass.

Sample Input 1

10 2 3
abccabaabb

Sample Output 1

Yes
Yes
No
No
Yes
Yes
Yes
No
No
No

The first, second, fifth, sixth, and seventh participants pass the Qualification contests.

Sample Input 2

12 5 2
cabbabaacaba

Sample Output 2

No
Yes
Yes
Yes
Yes
No
Yes
Yes
No
Yes
No
No

The sixth participant is third among overseas students and thus does not pass the Qualification contests.

Sample Input 3

5 2 2
ccccc

Sample Output 3

No
No
No
No
No

Solution in Rust (1.42.0) (judge verdict: Accepted)

#[allow(unused_macros, dead_code)]
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        let mut next = || { iter.next().unwrap() };
        input_inner!{next, $($r)*}
    };
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String{
            bytes
                .by_ref()
                .map(|r|r.unwrap() as char)
                .skip_while(|c|c.is_whitespace())
                .take_while(|c|!c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

#[allow(unused_macros, dead_code)]
macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};

    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };

    ($next:expr, mut $var:ident : $t:tt $($r:tt)*) => {
        let mut $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}

#[allow(unused_macros, dead_code)]
macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => {
        ( $(read_value!($next, $t)),* )
    };

    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };

    ($next:expr, chars) => {
        read_value!($next, String).chars().collect::<Vec<char>>()
    };

    ($next:expr, bytes) => {
        read_value!($next, String).into_bytes()
    };

    ($next:expr, usize1) => {
        read_value!($next, usize) - 1
    };

    ($next:expr, $t:ty) => {
        $next().parse::<$t>().expect("Parse error")
    };
}

#[allow(dead_code)]
struct UnionFind {
    parent: Vec<usize>,
    rank: Vec<usize>,
    size: Vec<usize>,
}

#[allow(dead_code)]
impl UnionFind {
    fn new(n: usize) -> UnionFind {
        let mut p = vec![0; n];
        for i in 0..n {
            p[i] = i;
        }
        return UnionFind {
            parent: p,
            rank: vec![0; n],
            size: vec![1; n],
        };
    }

    fn find(&mut self, x: usize) -> usize {
        if x == self.parent[x] {
            x
        } else {
            let p = self.parent[x];
            let pr = self.find(p);
            self.parent[x] = pr;
            pr
        }
    }

    fn same(&mut self, a: usize, b: usize) -> bool {
        self.find(a) == self.find(b)
    }

    fn unite(&mut self, a: usize, b: usize) {
        let a_root = self.find(a);
        let b_root = self.find(b);
        if a_root == b_root {
            return;
        }
        if self.rank[a_root] > self.rank[b_root] {
            self.parent[b_root] = a_root;
            self.size[a_root] += self.size[b_root];
        } else {
            self.parent[a_root] = b_root;
            self.size[b_root] += self.size[a_root];
            if self.rank[a_root] == self.rank[b_root] {
                self.rank[b_root] += 1;
            }
        }
    }

    fn get_size(&mut self, x: usize) -> usize {
        let root = self.find(x);
        self.size[root]
    }
}

const MOD_P: usize = 1000000007;

#[allow(dead_code)]
// fact(n) = n! mod p
fn fact(n: usize) -> usize {
    let mut acc = 1;
    for i in 1..n + 1 {
        acc = acc * i % MOD_P;
    }
    acc
}

#[allow(dead_code)]
fn mod_pow(b: usize, mut e: usize) -> usize {
    let mut base = b;
    let mut acc = 1;

    while e > 1 {
        if e % 2 == 1 {
            acc = acc * base % MOD_P;
        }
        e /= 2;
        base = base * base % MOD_P;
    }

    if e == 1 {
        acc = acc * base % MOD_P;
    }

    acc
}

#[allow(dead_code)]
fn comb(n: usize, r: usize) -> usize {
    // nCr = n! / (r! (n-r)!) = n! (r!)^(p-2) ((n-r)!)^(p-2)
    let x = ((n - r + 1)..(n + 1)).fold(1, |p, x| p * x % MOD_P);
    let y = mod_pow(fact(r), MOD_P - 2);
    x * y % MOD_P
}

#[derive(Clone, Copy, Debug)]
struct GF(usize);

impl std::ops::Add for GF {
    type Output = GF;
    fn add(self, rhs: GF) -> Self::Output {
        let mut d = self.0 + rhs.0;
        if d >= MOD_P {
            d -= MOD_P;
        }
        GF(d)
    }
}

impl std::ops::AddAssign for GF {
    fn add_assign(&mut self, rhs: GF) {
        *self = *self + rhs;
    }
}

impl std::ops::Sub for GF {
    type Output = GF;
    fn sub(self, rhs: GF) -> Self::Output {
        let mut d = self.0 + MOD_P - rhs.0;
        if d >= MOD_P {
            d -= MOD_P;
        }
        GF(d)
    }
}

impl std::ops::SubAssign for GF {
    fn sub_assign(&mut self, rhs: GF) {
        *self = *self - rhs;
    }
}

impl std::ops::Mul for GF {
    type Output = GF;
    fn mul(self, rhs: GF) -> Self::Output {
        let mut d = self.0 * rhs.0;
        d %= MOD_P;
        GF(d)
    }
}

impl std::ops::MulAssign for GF {
    fn mul_assign(&mut self, rhs: GF) {
        *self = *self * rhs;
    }
}
impl std::ops::Div for GF {
    type Output = GF;
    fn div(self, rhs: GF) -> Self::Output {
        let mut d = self.0 * rhs.inv().0;
        d %= MOD_P;
        GF(d)
    }
}

impl std::ops::DivAssign for GF {
    fn div_assign(&mut self, rhs: GF) {
        *self = *self / rhs;
    }
}

impl std::fmt::Display for GF {
    fn fmt<'a>(&self, f: &mut std::fmt::Formatter<'a>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

#[allow(dead_code)]
impl GF {
    pub fn new(n: usize) -> GF {
        GF(n % MOD_P)
    }
    pub fn zero() -> GF {
        GF(0)
    }
    pub fn one() -> GF {
        GF(1)
    }
    pub fn pow(self, mut e: usize) -> GF {
        let mut acc = GF::one();
        let mut b = self;
        while e > 1 {
            if e % 2 == 1 {
                acc *= b;
            }
            b *= b;
            e /= 2;
        }
        if e == 1 {
            acc *= b;
        }
        acc
    }
    pub fn fact(self) -> GF {
        let mut acc = GF::one();
        for i in 1..=self.0 {
            acc *= GF::new(i);
        }
        acc
    }
    pub fn inv(self) -> GF {
        self.pow(MOD_P - 2)
    }
    pub fn comb(n: GF, r: GF) -> GF {
        // nCr = n! / (r! (n-r)!) = n! (r!)^(p-2) ((n-r)!)^(p-2)
        let x = ((n.0 - r.0 + 1)..=n.0).fold(GF::one(), |p, x| p * GF(x));
        let y = r.fact().inv();
        x * y
    }
}

#[allow(dead_code)]
#[derive(Debug)]
struct MemComb {
    inv: Vec<GF>,
    fact: Vec<GF>,
    factinv: Vec<GF>,
}

#[allow(dead_code)]
impl MemComb {
    pub fn new(n: usize) -> MemComb {
        let mut inv = vec![GF::one(); n + 1];
        let mut fact = vec![GF::one(); n + 1];
        let mut factinv = vec![GF::one(); n + 1];

        for i in 2..=n {
            fact[i] = fact[i - 1] * GF(i);
        }

        factinv[n] = fact[n].inv();
        for i in (1..n).rev() {
            factinv[i] = factinv[i + 1] * GF(i + 1); // 1/n! = 1/(n+1)! * (n+1)
            inv[i] = factinv[i] * fact[i - 1]; // 1/n = 1/n! * (n-1)!
        }
        inv[n] = factinv[n] * fact[n - 1];

        MemComb { inv, fact, factinv }
    }
    pub fn comb(&self, n: usize, r: usize) -> GF {
        if n >= r {
            self.fact[n] * self.factinv[r] * self.factinv[n - r]
        } else {
            GF::zero()
        }
    }
}

#[allow(dead_code)]
fn gcd(a: usize, b: usize) -> usize {
    if b > a {
        gcd(b, a)
    } else if a % b == 0 {
        b
    } else {
        gcd(b, a % b)
    }
}

#[allow(dead_code)]
fn getline() -> String {
    let mut __ret = String::new();
    std::io::stdin().read_line(&mut __ret).ok();
    return __ret;
}

#[allow(unused_imports)]
use std::cmp::{max, min};

fn main() {
    input! {
        n: usize,
        a: usize,
        b: usize,
        s: chars,
    }
    let mut acc = 0;
    let mut foreigner = 0;
    for &c in &s {
        if acc >= a+b {
            println!("No");
        } else if c == 'a' {
            acc += 1;
            println!("Yes");
        } else if c == 'b' {
            if foreigner < b && acc < a+b {
                println!("Yes");
                acc += 1;
            } else {
                println!("No");
            }
            foreigner += 1;
        } else {
            println!("No");
        }
    }
}