結果
| 問題 |
No.515 典型LCP
|
| コンテスト | |
| ユーザー |
tubo28
|
| 提出日時 | 2017-06-06 17:40:45 |
| 言語 | Rust (1.83.0 + proconio) |
| 結果 |
AC
|
| 実行時間 | 246 ms / 1,000 ms |
| コード長 | 10,516 bytes |
| コンパイル時間 | 14,030 ms |
| コンパイル使用メモリ | 400,372 KB |
| 実行使用メモリ | 71,368 KB |
| 最終ジャッジ日時 | 2024-09-22 11:48:44 |
| 合計ジャッジ時間 | 16,797 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 15 |
コンパイルメッセージ
warning: field `n` is never read
--> src/main.rs:270:5
|
269 | struct SparceTable<T> {
| ----------- field in this struct
270 | n: usize,
| ^
|
= note: `#[warn(dead_code)]` on by default
ソースコード
fn main() {
let mut input_buffer = String::with_capacity(cp_io::BUFFER_SIZE);
let mut output_buffer = Vec::with_capacity(cp_io::BUFFER_SIZE);
unsafe {
cp_io::input::buf = &mut output_buffer;
cp_io::output::buf = &mut input_buffer;
}
std::thread::Builder::new()
.stack_size(104_857_600)
.spawn(solve)
.unwrap()
.join()
.unwrap();
cp_io::output::flush();
}
#[macro_use]
#[allow(dead_code, non_upper_case_globals, unused_macros)]
mod cp_io {
pub const BUFFER_SIZE: usize = 8192;
#[macro_use]
pub mod output {
pub const ENABLE_DUMP: bool = true;
pub const PRECISION: usize = 10;
pub static mut buf: *mut String = 0 as *mut String;
macro_rules! p {
($x: expr) => {{
$x.output();
"\n".output();
unsafe {
if (*cp_io::output::buf).len() > cp_io::BUFFER_SIZE {
flush();
}
}
}};
($x: expr, $($y: expr),+) => {{
$x.output();
" ".output();
p!($($y),+);
}};
}
macro_rules! pf {
($($x: expr),+) => {{
p!($($x),+);
flush();
}};
}
macro_rules! d {
($($a: expr),+) => {
if ENABLE_DUMP {
use std::io::*;
write!(stderr(), "{}:{}\t", file!(), line!()).unwrap();
d!(A $($a),+);
write!(stderr(), " = ").unwrap();
d!(B $($a),+);
write!(stderr(), "\n").unwrap();
stderr().flush().unwrap();
}
};
(A $x: expr) => {
write!(stderr(), "{}", stringify!($x)).unwrap();
};
(A $x: expr, $($y: expr),+) => {
write!(stderr(), "{}, ", stringify!($x)).unwrap();
d!(A $($y),+);
};
(B $x: expr) => {
write!(stderr(), "{:?}", $x).unwrap();
};
(B $x: expr, $($y: expr),+) => {
write!(stderr(), "{:?}, ", $x).unwrap();
d!(B $($y),+);
};
}
pub trait Output {
fn output(&self);
}
macro_rules! output_normal {
($t: ty) => {
impl Output for $t {
fn output(&self) {
unsafe {
use std::fmt::Write;
write!(&mut *buf, "{}", self).unwrap();
}
}
}
};
($t: ty, $($u: ty),+) => {
output_normal!($t);
output_normal!($($u),+);
};
}
macro_rules! output_float {
($t: ty) => {
impl Output for $t {
fn output(&self) {
unsafe {
use std::fmt::Write;
write!(&mut *buf, "{:.*}", PRECISION, self).unwrap();
}
}
}
};
($t: ty, $($u: ty),+) => {
output_float!($t);
output_float!($($u),+);
};
}
pub fn flush() {
unsafe {
print!("{}", *buf);
use std::io::*;
stdout().flush().unwrap();
(*buf).clear();
}
}
output_normal!(u8, u16, u32, u64, usize);
output_normal!(i8, i16, i32, i64, isize);
output_normal!(bool, &'static str, String);
output_float!(f32, f64);
}
pub mod input {
pub trait Input<T> {
fn input() -> T;
}
macro_rules! input_primitive {
($t: ty) => {
impl Input<$t> for $t {
fn input() -> $t {
get_word().expect("EOF?").parse()
.unwrap_or_else(|e| panic!("Cannot parse {}", e))
}
}
};
($t: ty, $($u: ty),+) => {
input_primitive!($t);
input_primitive!($($u),+);
};
}
macro_rules! input_tuple {
($($t: ident),*) => {
impl< $($t: Input<$t>),* > Input< ( $($t),* ) > for ( $($t),* ) {
fn input() -> ( $($t),* ) {
( $( $t::input()),* )
}
}
};
}
input_primitive!(u8, u16, u32, u64, usize);
input_primitive!(i8, i16, i32, i64, isize);
input_primitive!(bool, String);
input_tuple!(A, B);
input_tuple!(A, B, C);
input_tuple!(A, B, C, D);
pub fn get<T: Input<T>>() -> T {
T::input()
}
pub fn get_vec<T: Input<T>>(n: usize) -> Vec<T> {
(0..n).map(|_| get()).collect()
}
pub fn get_mat<T: Input<T>>(r: usize, c: usize) -> Vec<Vec<T>> {
(0..r).map(|_| get_vec(c)).collect()
}
pub fn get_vec_char() -> Vec<char> {
get_word().unwrap().chars().collect()
}
pub fn get_mat_char(h: usize) -> Vec<Vec<char>> {
(0..h).map(|_| get_vec_char()).collect()
}
pub fn get_line() -> String {
get_line_wrapped().unwrap()
}
fn get_word() -> Option<String> {
let mut res = String::with_capacity(18);
while let Some(c) = get_u8() {
let d = c as char;
if !d.is_whitespace() {
res.push(d);
} else if res.len() != 0 {
unget_u8(c);
break;
}
}
if res.len() == 0 { None } else { Some(res) }
}
fn get_line_wrapped() -> Option<String> {
let c = get_u8();
if c.is_none() {
return None;
}
let mut line = String::with_capacity(18);
line.push(c.unwrap() as char);
loop {
let c = get_u8();
if c.is_none() || c.unwrap() == b'\n' {
// コメントはC++等での仕様
// if c.is_some() {
// self.unget_u8(b'\n');
// }
return Some(line);
}
line.push(c.unwrap() as char);
}
}
pub fn has_next() -> bool {
loop {
let c = get_u8();
if c.is_none() {
return false;
}
let c = c.unwrap();
if !(c as char).is_whitespace() {
unget_u8(c);
return true;
}
}
}
pub static mut buf: *mut Vec<u8> = 0 as *mut Vec<u8>;
fn get_u8() -> Option<u8> {
unsafe {
let b = &mut (*buf);
use std::io::{stdin, Read};
if let Some(c) = b.pop() {
Some(c as u8)
} else {
b.resize(super::BUFFER_SIZE, 0);
match stdin().read(b) {
Ok(l) if l > 0 => {
b.truncate(l);
b.reverse();
b.pop()
}
_ => return None,
}
}
}
}
fn unget_u8(c: u8) {
unsafe { (*buf).push(c) }
}
}
}
struct SparceTable<T> {
n: usize,
min: Vec<Vec<T>>,
log2: Vec<usize>,
}
impl<T: Copy + Ord> SparceTable<T> {
pub fn new<I>(it: I) -> SparceTable<T>
where I: IntoIterator<Item=T> {
let it = it.into_iter();
let v = it.collect::<Vec<T>>();
let n = v.len();
let mut log2 = vec![0; n + 1];
log2[1] = 0;
for i in 2..log2.len() {
log2[i] = log2[i/2] + 1;
}
let mut res = SparceTable {
n: n,
min: vec![v],
log2: log2,
};
for i in 1..30 {
let w = 1 << i;
if n + 1 < w {
break;
}
let next = (0..n + 1 - w).map(|l| {
std::cmp::min(res.min[i - 1][l], res.min[i - 1][l + w/2])
}).collect();
res.min.push(next);
}
res
}
pub fn rmq(&self, l: usize, r: usize) -> T {
let i = self.log2[r - l];
let rr = r - (1 << i);
// assert!(r - (1 << i) == rr);
std::cmp::min(self.min[i][l], self.min[i][rr])
}
}
#[allow(unused_imports)]
use cp_io::input::*;
#[allow(unused_imports)]
use cp_io::output::*;
fn lcp_len(a: &Vec<char>, b: &Vec<char>) -> usize {
let mut i = 0;
while i < a.len() && i < b.len() && a[i] == b[i] {
i += 1;
}
i
}
fn solve() {
while has_next() {
let n = get();
let s = get_mat_char(n);
let mut idx = (0..n).collect::<Vec<_>>();
idx.sort_by(|&i, &j| s[i].cmp(&s[j]));
let mut ridx = vec![0; n];
for i in 0..n {
ridx[idx[i]] = i;
}
let (m, mut x, d): (usize, u64, u64) = get();
let mut i = vec![0usize; m];
let mut j = vec![0usize; m];
for k in 0..m {
let n = n as u64;
i[k] = ((x / (n - 1)) + 1) as usize;
j[k] = ((x % (n - 1)) + 1) as usize;
if i[k] > j[k] {
std::mem::swap(&mut i[k], &mut j[k]);
} else {
j[k] = j[k] + 1;
}
x = (x + d) % (n * (n - 1));
}
let lcp: Vec<_> = (0..n-1).map(|i| {
lcp_len(&s[idx[i]], &s[idx[i+1]])
}).collect();
let st = SparceTable::new(lcp.iter());
let mut res: usize = 0;
for (&i, &j) in i.iter().zip(j.iter()) {
let (i, j) = (i - 1, j - 1);
let (l, r) = if ridx[i] < ridx[j] {
(ridx[i], ridx[j])
} else {
(ridx[j], ridx[i])
};
// d!(l, r);
res += *st.rmq(l, r);
}
p!(res);
}
}
tubo28