Cod sursa(job #2639833)

Utilizator TincaMateiTinca Matei TincaMatei Data 4 august 2020 02:32:28
Problema Cautare binara Scor 100
Compilator rs Status done
Runda Arhiva educationala Marime 3.04 kb
use std::fs::File;
use std::io::{Write, BufReader, BufWriter, BufRead};

// Suppose we have a function 'search' that returns false for all values until x and true for all other values
// Iterating through it will perform a binary search
// iter.last() will return a pair of i32 such that search(left) = false, search(right) = true and left + 1 == right
// The first 'left' and 'right' should be both be undefined values of the search domain
struct BinSearchIterator<T> 
where T: Fn(i32) -> bool {
  left: i32,
  right: i32,
  search: T,
}

impl<T> BinSearchIterator<T>
where T: Fn(i32) -> bool {
  fn new(left: i32, right: i32, search: T) -> BinSearchIterator<T> {
    BinSearchIterator {
      left,
      right,
      search
    }
  }
}

impl<T> Iterator for BinSearchIterator<T>
where T: Fn(i32) -> bool{
  type Item = (i32, i32);

  fn next(&mut self) -> Option<Self::Item>{
    if self.right - self.left > 1 {
      let mid = (self.left + self.right) / 2;

      if (self.search)(mid) {
        self.right = mid;
      } else {
        self.left = mid;
      }

      Some((self.left, self.right))
    } else if self.left < self.right {
      let res = Some((self.left, self.right));
      self.left = self.right;
      res
    } else {
      None
    }
  }
}

fn main() {
  let mut fin = BufReader::new(File::open("cautbin.in").unwrap());
  let mut fout = BufWriter::new(File::create("cautbin.out").unwrap());

  let mut line = String::new();
  fin.read_line(&mut line).unwrap();
  
  let n : usize = line.trim().parse().unwrap();
  
  let mut line = String::new();
  fin.read_line(&mut line).unwrap();

  let v : Vec<i32> = line.trim()
                         .split(' ')
                         .map(|x| { x.parse().unwrap() } )
                         .collect();

  assert_eq!(v.len(), n);

  let mut line = String::new();
  fin.read_line(&mut line).unwrap();
  let m : usize = line.trim().parse().unwrap();

  for _ in 0..m {
    let mut line = String::new();
    fin.read_line(&mut line).unwrap();
    let arg : Vec<i32> = line.trim().split(' ').map(|x| {x.parse().unwrap() } ).collect();
    assert_eq!(arg.len(), 2);

    let optype = arg[0];
    let x = arg[1];

    match optype {
    0 => {
      let bs = BinSearchIterator::new(-1, n as i32, |t| -> bool { v[t as usize] > x });
      
      let (left, _right) = bs.last().unwrap();

      let res = if left == -1 || v[left as usize] != x { -1 } else { left + 1 };
      fout.write(format!("{}\n", res).as_bytes()).unwrap();
    }
    1 => {
      let res = BinSearchIterator::new(-1, n as i32, |t| -> bool { v[t as usize] > x }).last()
                                                                                        .unwrap().0 + 1;
      fout.write(format!("{}\n", res).as_bytes()).unwrap();
    }
    2 => {
      let res = BinSearchIterator::new(-1, n as i32, |t| -> bool { v[t as usize] >= x }).last()
                                                                                       .unwrap().1 + 1;
      fout.write(format!("{}\n", res).as_bytes()).unwrap();
    }
    _ => {
    }
    }
  }

  fout.flush().unwrap();
}