Problem:
Score : 300 points

Problem Statement

Given is a string S of length N-1.
Each character in S is < or >.

A sequence of N non-negative integers, a_1,a_2,\cdots,a_N, is said to be good when the following condition is satisfied for all i (1 \leq i \leq N-1):

If S_i= <: a_i<a_{i+1}

If S_i= >: a_i>a_{i+1}

Find the minimum possible sum of the elements of a good sequence of N non-negative integers.

Constraints

2 \leq N \leq 5 \times 10^5

S is a string of length N-1 consisting of < and >.

Input

Input is given from Standard Input in the following format:

S

Output

Find the minimum possible sum of the elements of a good sequence of N non-negative integers.

Sample Input 1

<>>

Sample Output 1

3

a=(0,2,1,0) is a good sequence whose sum is 3.
There is no good sequence whose sum is less than 3.

Sample Input 2

<>>><<><<<<<>>><

Sample Output 2

28

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

fn main(){
    let a: String = linp();
    let mut n = 0u64;
    let mut last = '0';
    let mut prev = 0u64;
    let mut sum = 0u64;
    for c in a.chars(){
        if last != c{
            if c == '<'{
                sum += if n < prev{prev}else{n};
                prev = 0;
            }else{
                prev = n;
            }
            n = 0;
        }else{
            sum += n;
        }
        n += 1;
        last = c;
    }
    if last == '<'{
        sum += n;
    }else{
        sum += if n < prev{prev}else{n};
    }
    println!("{}", sum);
}

// easy IOs
trait SimpleParse{
    fn simple_parse(s: &str) -> Self;
    fn get_slice_index(s: &str) -> Option<usize>{
        s.find(|c|{c == ' ' || c == '\t' || c == '\n'})
    }
    fn next_vec_item<'a>(s: &'a str) -> Option<&'a str>{
        match s.find(|c|{!(c == ' ' || c == '\t' || c == '\n')}){
            Some(i) => Some(&s[i..]),
            None => None
        }
    }
}
macro_rules! new_parse{
    ( $t:ty ) => {
        impl SimpleParse for $t{
            fn simple_parse(s: &str) -> Self{
                s.trim().parse().expect("input parse error")
            }
        }
    }
}
macro_rules! new_tparse{
    ( $a:ident: $A:ident; $($x:ident: $X:ident, $y:ident: $Y:ident);* ) => {
        impl<$A, $($Y),*> SimpleParse for ($A, $($Y),*)
        where $A: SimpleParse, $($Y: SimpleParse),* {
            fn simple_parse($a: &str) -> Self{
                $(
                    let $x = $x.trim();
                    let ($x, $y) = $x.split_at(
                            $X::get_slice_index($x)
                            .expect("not enough inputs")
                    );
                )*
                ($A::simple_parse($a), $($Y::simple_parse($y)),*)
            }
            fn get_slice_index(s: &str) -> Option<usize>{
                let ret = $A::get_slice_index(s);
                $(
                    let ret = ret.expect("not enough inputs");
                    let ret = (&s[ret..])
                        .find(|c|{!(c == ' ' || c == '\t' || c == '\n')})
                        .expect("not enough inputs");
                    let ret = $Y::get_slice_index(&s[ret..]);
                )*
                ret
            }
        }
    }
}
impl SimpleParse for String{
    fn simple_parse(s: &str) -> String{
        String::from(s.trim())
    }
}
impl SimpleParse for char{
    fn simple_parse(s: &str) -> char{
        if s.len() != 1{
            panic!("char input error");
        }
        s.chars().nth(0).unwrap()
    }
    fn get_slice_index(s: &str) -> Option<usize>{
        if s.len() < 1{
            None
        }else{
            Some(1)
        }
    }
    fn next_vec_item<'a>(s: &'a str) -> Option<&'a str>{
        if s.len() == 0{
            None
        }else{
            Some(s)
        }
    }
}
impl<T> SimpleParse for Vec<T>
where T: SimpleParse{
    fn simple_parse(s: &str) -> Vec<T>{
        let mut ret: Vec<T> = Vec::new();
        let mut s = s.trim();
        if s.len() == 0{
            return ret;
        }
        loop{
            match T::get_slice_index(s){
                Some(i) => {
                    let (a, b) = s.split_at(i);
                    ret.push(T::simple_parse(a));
                    match T::next_vec_item(b){
                        Some(ss) => {s = ss;}
                        None => {return ret;}
                    }
                }
                None => {
                    ret.push(T::simple_parse(s));
                    return ret;
                }
            }
        }
    }
    fn get_slice_index(_: &str) -> Option<usize>{
        None
    }
}
impl<A> SimpleParse for (A,)
where A: SimpleParse {
    fn simple_parse(s: &str) -> Self{
        (A::simple_parse(s),)
    }
}
new_parse!(i8);
new_parse!(u8);
new_parse!(i16);
new_parse!(u16);
new_parse!(i32);
new_parse!(u32);
new_parse!(i64);
new_parse!(u64);
new_parse!(f32);
new_parse!(f64);
new_parse!(isize);
new_parse!(usize);
new_tparse!(a:A; a:A,b:B);
new_tparse!(a:A; a:A,b:B; b:B,c:C);
new_tparse!(a:A; a:A,b:B; b:B,c:C; c:C,d:D);
new_tparse!(a:A; a:A,b:B; b:B,c:C; c:C,d:D; d:D,e:E);
new_tparse!(a:A; a:A,b:B; b:B,c:C; c:C,d:D; d:D,e:E; e:E,f:F);
new_tparse!(a:A; a:A,b:B; b:B,c:C; c:C,d:D; d:D,e:E; e:E,f:F; f:F,g:G);
new_tparse!(a:A; a:A,b:B; b:B,c:C; c:C,d:D; d:D,e:E; e:E,f:F; f:F,g:G; g:G,h:H);
#[allow(dead_code)]
fn lin() -> String{
    let mut input = String::new();
    let _ = std::io::stdin().read_line(&mut input).expect("input error");
    input
}
#[allow(dead_code)]
fn linp<A: SimpleParse>() -> A{
    A::simple_parse(lin().trim())
}