Submission #47599112
Source Code Expand
#![allow(non_snake_case)]
fn main(){
let _=std::thread::Builder::new().name("run".to_string()).stack_size(32*1024*1024).spawn(run).unwrap().join();
}
fn run(){
get_time();
let input=Input::input();
let ans=solve(&input);
println!("{}",ans.len());
for &n in &ans{
let (i0,j0)=input.to_pos[n.0];
let (i1,j1)=input.to_pos[n.1];
println!("{} {} {} {}",i0,j0,i1,j1);
}
}
fn solve(input:&Input)->Vec<(usize,usize)>{
let state=State::new(input);
let node={
let mut n=0;
while state.isok(input,n){
n+=1;
}
let score=state.score(input,n);
let hash=state.hash(input,n);
Node{
op:[(!0,!0);2],
parent:!0,
child:!0,
prev:!0,
next:!0,
score,n,hash,
prev_pos:!0,
refs:0,
valid:0,
}
};
let mut solver=BeamSearch::new(state.clone(),node.clone());
let mut best=vec![];
let mut best_score=!0;
let mut iter=0;
loop{
iter+=1;
solver.reset(state.clone(),node.clone());
let res=solver.solve(input);
if res.is_empty(){
break;
}
if best_score>res.len(){
best_score=res.len();
best=res;
}
}
eprintln!("iter = {}",iter);
eprintln!("score = {}",best_score);
eprintln!("time = {}",get_time());
best
}
const ENDED_BONUS:i64=1200;
static mut RR:usize=30;
#[allow(non_camel_case_types)]
type uint=u32;
#[derive(Clone)]
struct State{
state:[usize;L+1],
pos:[usize;L],
}
impl State{
fn new(input:&Input)->State{
let mut pos=[!0;L];
for (i,&n) in input.grid.iter().enumerate(){
pos[n]=i;
}
let mut state=[0;L+1];
state[..L].copy_from_slice(&input.grid);
State{state,pos}
}
fn isok(&self,input:&Input,n:usize)->bool{
if n==465{
return false;
}
let p=self.pos[n];
let np0=input.dd[p][0];
let np1=input.dd[p][1];
n>=self.state[np0] && n>=self.state[np1]
}
fn score(&self,input:&Input,n:usize)->i64{
(0..L).map(|i|
input.height[i]*self.state[i] as i64
).sum::<i64>()
+n as i64*ENDED_BONUS
}
fn hash(&self,input:&Input,n:usize)->u64{
let mut hash=0;
for i in 0..n{
hash^=input.zob[self.pos[i]];
}
hash
}
fn apply(&mut self,node:&Node){
self.swap(node.op[0]);
self.swap(node.op[1]);
}
fn revert(&mut self,node:&Node){
self.swap(node.op[1]);
self.swap(node.op[0]);
}
fn swap(&mut self,(p0,p1):(usize,usize)){
if p0==L{
return;
}
self.pos.swap(self.state[p0],self.state[p1]);
self.state.swap(p0,p1);
}
}
#[derive(Clone)]
struct Cand{
op:[(usize,usize);2],
parent:uint,
eval_score:i64,
hash:u64,
n:usize,
score:i64,
prev_pos:usize,
pos:usize,
}
impl Cand{
fn raw_score(&self,input:&Input)->i64{
self.score
}
fn to_node(&self)->Node{
Node{
child:!0,
prev:!0,
next:!0,
op:self.op,
parent:self.parent,
score:self.score,
n:self.n,
hash:self.hash,
prev_pos:self.prev_pos,
valid:0,
refs:0,
}
}
}
#[derive(Clone,Default)]
struct Node{
op:[(usize,usize);2],
parent:uint,
child:uint,
prev:uint,
next:uint,
score:i64,
n:usize,
hash:u64,
prev_pos:usize,
refs:u8,
valid:u16,
}
const MAX_WIDTH:usize=300;
// const TURN:usize=100;
#[derive(Clone)]
struct BeamSearch{
state:State,
nodes:Vec<Node>,
que:Vec<uint>,
cur_node:usize,
free:Vec<uint>,
at:u16,
}
impl BeamSearch{
fn new(state:State,node:Node)->BeamSearch{
const MAX_NODES:usize=MAX_WIDTH*10;
assert!(MAX_NODES<uint::MAX as usize,"uintのサイズが足りないよ");
let mut nodes=vec![Node::default();MAX_NODES];
nodes[0]=node;
let free=(1..MAX_NODES as uint).rev().collect();
BeamSearch{
state,nodes,free,
que:Vec::with_capacity(MAX_WIDTH),
cur_node:0,
at:0,
}
}
fn reset(&mut self,state:State,mut node:Node){
self.state=state;
self.at+=1;
node.valid=self.at;
self.nodes[0]=node;
self.free.clear();
self.free.extend((1..self.nodes.len() as uint).rev());
self.que.clear();
self.cur_node=0;
}
fn add_node(&mut self,cand:Cand){
let next=self.nodes[cand.parent as usize].child;
let new=self.free.pop().unwrap_or_else(||{
let n=self.nodes.len() as uint;
assert!(n!=0,"uintのサイズが足りないよ");
self.nodes.push(Node::default());
n
});
if next!=!0{
self.nodes[next as usize].prev=new;
}
self.nodes[cand.parent as usize].child=new;
self.nodes[new as usize]=Node{next,..cand.to_node()};
self.retarget(new);
}
fn del_node(&mut self,mut idx:uint){
assert!(self.nodes[idx as usize].refs==0);
loop{
self.free.push(idx);
let Node{prev,next,parent,..}=self.nodes[idx as usize];
assert_ne!(parent,!0,"全てのノードを消そうとしています");
self.nodes[parent as usize].refs-=1;
if prev&next==!0 && self.nodes[parent as usize].refs==0{
idx=parent;
continue;
}
if prev!=!0{
self.nodes[prev as usize].next=next;
}
else{
self.nodes[parent as usize].child=next;
}
if next!=!0{
self.nodes[next as usize].prev=prev;
}
break;
}
}
fn dfs(&mut self,input:&Input,turn:usize,cands:&mut Vec<Vec<Cand>>,single:bool){
if self.nodes[self.cur_node].child==!0{
let cnt=self.append_cands(input,turn,self.cur_node,cands);
if cnt==0{
self.que.push(self.cur_node as uint);
}
self.nodes[self.cur_node].refs+=cnt;
return;
}
let node=self.cur_node;
let mut child=self.nodes[node].child;
let next_single=single&(self.nodes[child as usize].next==!0);
// let prev_state=self.state.clone();
'a: loop{
while self.nodes[child as usize].valid!=self.at{
child=self.nodes[child as usize].next;
if child==!0{
break 'a;
}
}
self.cur_node=child as usize;
self.state.apply(&self.nodes[child as usize]);
self.dfs(input,turn,cands,next_single);
if !next_single{
self.state.revert(&self.nodes[child as usize]);
// assert!(prev_state==self.state);
}
child=self.nodes[child as usize].next;
if child==!0{
break;
}
}
if !next_single{
self.cur_node=node;
}
}
fn no_dfs(&mut self,input:&Input,turn:usize,cands:&mut Vec<Vec<Cand>>){
loop{
let Node{next,child,..}=self.nodes[self.cur_node];
if next==!0 || child==!0{
break;
}
self.cur_node=child as usize;
self.state.apply(&self.nodes[self.cur_node]);
}
assert!(self.nodes[self.cur_node].valid==self.at);
let root=self.cur_node;
loop{
assert!(self.nodes[self.cur_node].valid==self.at);
let mut child=self.nodes[self.cur_node].child;
if child==!0{
let cnt=self.append_cands(input,turn,self.cur_node,cands);
if cnt==0{
self.que.push(self.cur_node as uint);
}
self.nodes[self.cur_node].refs+=cnt;
'a: loop{
if self.cur_node==root{
return;
}
let node=&self.nodes[self.cur_node];
self.state.revert(&node);
let mut next=node.next;
loop{
if next==!0{
self.cur_node=node.parent as usize;
break;
}
if self.nodes[next as usize].valid==self.at{
self.cur_node=next as usize;
self.state.apply(&self.nodes[self.cur_node]);
break 'a;
}
next=self.nodes[next as usize].next;
}
}
}
else{
while self.nodes[child as usize].valid!=self.at{
child=self.nodes[child as usize].next;
}
self.cur_node=child as usize;
self.state.apply(&self.nodes[self.cur_node]);
}
}
}
fn enum_cands(&mut self,input:&Input,turn:usize,cands:&mut Vec<Vec<Cand>>){
assert_eq!(self.nodes[self.cur_node].valid,self.at);
self.que.clear();
// self.dfs(input,turn,cands,true);
self.no_dfs(input,turn,cands);
}
fn retarget(&mut self,mut idx:uint){
while self.nodes[idx as usize].valid!=self.at{
self.nodes[idx as usize].valid=self.at;
if idx as usize==self.cur_node{
break;
}
idx=self.nodes[idx as usize].parent;
}
}
fn update<I:Iterator<Item=(Cand,bool)>>(&mut self,cands:I){
self.at+=1;
for i in 0..self.que.len(){
self.del_node(self.que[i]);
}
for (cand,f) in cands{
let node=&mut self.nodes[cand.parent as usize];
if f{
self.add_node(cand);
} else{
node.refs-=1;
if node.refs==0{
self.del_node(cand.parent);
}
}
}
}
fn restore(&self,mut idx:uint)->Vec<(usize,usize)>{
let mut ret=vec![];
loop{
let Node{op,parent,..}=self.nodes[idx as usize];
if parent==!0{
break;
}
if op[1].0!=L{
ret.push(op[1]);
}
ret.push(op[0]);
idx=parent;
}
ret.reverse();
ret
}
fn append_cands(&mut self,input:&Input,turn:usize,idx:usize,cands:&mut Vec<Vec<Cand>>)->u8{
let node=&self.nodes[idx];
assert_eq!(node.child,!0);
// assert_eq!(node.score,self.state.score(input,node.n));
// assert_eq!(node.hash,self.state.hash(input,node.n));
let pos=self.state.pos[node.n];
let mut ret=0;
for &i in &[0,1,2,5]{
let np=input.dd[pos][i];
if node.n>=self.state.state[np] || np==node.prev_pos{
continue;
}
let mut score=node.score;
self.state.swap((pos,np));
let mut n=node.n;
let mut hash=node.hash;
while self.state.isok(input,n){
let pos=self.state.pos[n];
hash^=input.zob[pos];
n+=1;
}
let tp=*self.state.pos.get(n).unwrap_or(&!0);
let prev_pos=if n!=node.n{
!0
} else {
pos
};
score+=ENDED_BONUS*(n-node.n) as i64;
self.state.swap((pos,np));
let nn=self.state.state[np];
let old=input.height[pos]*node.n as i64+input.height[np]*nn as i64;
let new=input.height[pos]*nn as i64+input.height[np]*node.n as i64;
score+=new-old;
let cand=Cand{
op:[(pos,np),(L,L)],
parent:idx as uint,
score,n,hash,
eval_score:score+(rnd::next()%unsafe{RR}) as i64,
prev_pos,
pos:tp,
};
cands[turn+1].push(cand);
ret+=1;
}
for &(np,op) in &input.dd2[pos]{
if node.n>=self.state.state[np] || np==node.prev_pos{
continue;
}
let mut score=node.score;
self.state.swap(op[0]);
self.state.swap(op[1]);
let mut n=node.n;
let mut hash=node.hash;
while self.state.isok(input,n){
let pos=self.state.pos[n];
hash^=input.zob[pos];
n+=1;
}
let tp=*self.state.pos.get(n).unwrap_or(&!0);
let prev_pos=if n!=node.n{
!0
} else {
pos
};
score+=ENDED_BONUS*(n-node.n) as i64;
self.state.swap(op[1]);
self.state.swap(op[0]);
let nn=self.state.state[np];
let mm=self.state.state[op[0].1];
let old=input.height[pos]*node.n as i64+input.height[op[0].1]*mm as i64+input.height[np]*nn as i64;
let new=input.height[pos]*nn as i64+input.height[op[0].1]*node.n as i64+input.height[np]*mm as i64;
score+=new-old;
let cand=Cand{
op,
parent:idx as uint,
score,n,hash,
eval_score:score+(rnd::next()%unsafe{RR}) as i64,
prev_pos,
pos:tp,
};
cands[turn+2].push(cand);
ret+=1;
}
ret
}
fn solve(&mut self,input:&Input)->Vec<(usize,usize)>{
use std::cmp::Reverse;
let M=MAX_WIDTH;
let mut cands=(0..=3000).map(|_|Vec::<Cand>::with_capacity(MAX_WIDTH*8)).collect::<Vec<_>>();
let mut first=true;
let mut set=NopHashSet::default();
let best;
let mut turn=0;
loop{
const R0:f64=40.;
const R1:f64=20.;
unsafe{
RR=(R0+(R1-R0)*(turn as f64/1900.)).round() as usize;
}
if !first{
let cands=&mut cands[turn];
assert!(!cands.is_empty());
if let Some(idx)=(0..cands.len()).find(|&i|cands[i].n==L){
best=cands[idx].clone();
break;
}
let M0=(M as f64*2.).round() as usize;
if cands.len()>M0{
cands.select_nth_unstable_by_key(M0,|a|Reverse(a.score));
}
let len=M0.min(cands.len());
cands[..len].sort_unstable_by_key(|a|Reverse(a.eval_score));
set.clear();
let mut total=0;
self.update(cands.drain(..).map(|cand|{
let f=total<M && set.insert(cand.hash^input.zob[cand.pos]);
total+=f as usize;
(cand,f)
}));
}
first=false;
self.enum_cands(input,turn,&mut cands);
turn+=1;
if turn&31==0 && get_time()>=1.95{
return vec![];
}
}
let mut ret=self.restore(best.parent);
ret.push(best.op[0]);
if best.op[1].0!=L{
ret.push(best.op[1]);
}
ret
}
}
const N:usize=30;
const L:usize=465;
use proconio::*;
use rand::prelude::*;
struct Input{
grid:[usize;L],
zob:[u64;L],
dd:[[usize;6];L],
dd2:[[(usize,[(usize,usize);2]);4];L],
height:[i64;L],
to_pos:[(usize,usize);L],
}
impl Input{
fn input()->Input{
let mut to_id=[[!0;N];N];
let mut it=0..;
let mut to_pos=[(!0,!0);L];
for i in 0..N{
for j in 0..=i{
to_id[i][j]=it.next().unwrap();
to_pos[to_id[i][j]]=(i,j);
}
}
input!{
i_grid:[usize;L]
}
let mut grid=[!0;L];
grid.copy_from_slice(&i_grid);
let mut zob=[!0;L];
let mut rng=rand_pcg::Pcg64Mcg::new(0);
for i in 0..L{
zob[i]=rng.gen();
}
let mut dd=[[L;6];L];
for &n in to_pos.iter(){
for (i,&d) in [(!0,!0),(!0,0),(0,1),(1,1),(1,0),(0,!0)].iter().enumerate(){
let np=(n.0+d.0,n.1+d.1);
if np.0<N && np.1<N && to_id[np.0][np.1]!=!0{
dd[to_id[n.0][n.1]][i]=to_id[np.0][np.1];
}
}
}
let mut height=[0;L];
for i in 0..L{
height[i]=(to_pos[i].0 as f64).powf(1.).round() as i64; // todo
}
let mut dd2=[[(L,[(L,L);2]);4];L];
for i in 0..L{
for j in 0..4{
let mp=dd[i][j&1];
if mp==L{
continue;
}
let np=dd[mp][j>>1];
dd2[i][j]=(np,[(np,mp),(mp,i)])
}
}
Input{grid,zob,dd,dd2,height,to_pos}
}
}
fn get_time()->f64{
static mut START:f64=-1.;
let time=std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs_f64();
unsafe{
if START<0.{
START=time;
}
#[cfg(local)]{
(time-START)*1.5
}
#[cfg(not(local))]{
time-START
}
}
}
#[allow(unused)]
mod nth{
use std::cmp;
use std::mem::{self, MaybeUninit};
use std::ptr;
struct CopyOnDrop<T> {
src: *const T,
dest: *mut T,
}
impl<T> Drop for CopyOnDrop<T> {
fn drop(&mut self) {
unsafe {
ptr::copy_nonoverlapping(self.src, self.dest, 1);
}
}
}
fn shift_tail<T, F>(v: &mut [T], is_less: &mut F)
where
F: FnMut(&T, &T) -> bool,
{
let len = v.len();
unsafe {
if len >= 2 && is_less(v.get_unchecked(len - 1), v.get_unchecked(len - 2)) {
let tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(len - 1)));
let v = v.as_mut_ptr();
let mut hole = CopyOnDrop { src: &*tmp, dest: v.add(len - 2) };
ptr::copy_nonoverlapping(v.add(len - 2), v.add(len - 1), 1);
for i in (0..len - 2).rev() {
if !is_less(&*tmp, &*v.add(i)) {
break;
}
ptr::copy_nonoverlapping(v.add(i), v.add(i + 1), 1);
hole.dest = v.add(i);
}
}
}
}
fn insertion_sort<T, F>(v: &mut [T], is_less: &mut F)
where
F: FnMut(&T, &T) -> bool,
{
for i in 1..v.len() {
shift_tail(&mut v[..i + 1], is_less);
}
}
fn partition_in_blocks<T, F>(v: &mut [T], pivot: &T, is_less: &mut F) -> usize
where
F: FnMut(&T, &T) -> bool,
{
const BLOCK: usize = 128;
let mut l = v.as_mut_ptr();
let mut block_l = BLOCK;
let mut start_l = ptr::null_mut();
let mut end_l = ptr::null_mut();
let mut offsets_l = [MaybeUninit::<u8>::uninit(); BLOCK];
let mut r = unsafe { l.add(v.len()) };
let mut block_r = BLOCK;
let mut start_r = ptr::null_mut();
let mut end_r = ptr::null_mut();
let mut offsets_r = [MaybeUninit::<u8>::uninit(); BLOCK];
fn width<T>(l: *mut T, r: *mut T) -> usize {
assert!(mem::size_of::<T>() > 0);
(r as usize - l as usize) / mem::size_of::<T>()
}
loop {
let is_done = width(l, r) <= 2 * BLOCK;
if is_done {
let mut rem = width(l, r);
if start_l < end_l || start_r < end_r {
rem -= BLOCK;
}
if start_l < end_l {
block_r = rem;
} else if start_r < end_r {
block_l = rem;
} else {
block_l = rem / 2;
block_r = rem - block_l;
}
debug_assert!(block_l <= BLOCK && block_r <= BLOCK);
debug_assert!(width(l, r) == block_l + block_r);
}
if start_l == end_l {
start_l = offsets_l.as_mut_ptr() as *mut _;
end_l = start_l;
let mut elem = l;
for i in 0..block_l {
unsafe {
*end_l = i as u8;
end_l = end_l.offset(!is_less(&*elem, pivot) as isize);
elem = elem.offset(1);
}
}
}
if start_r == end_r {
start_r = offsets_r.as_mut_ptr() as *mut _;
end_r = start_r;
let mut elem = r;
for i in 0..block_r {
unsafe {
elem = elem.offset(-1);
*end_r = i as u8;
end_r = end_r.offset(is_less(&*elem, pivot) as isize);
}
}
}
let count = cmp::min(width(start_l, end_l), width(start_r, end_r));
if count > 0 {
macro_rules! left {
() => {
l.offset(*start_l as isize)
};
}
macro_rules! right {
() => {
r.offset(-(*start_r as isize) - 1)
};
}
unsafe {
let tmp = ptr::read(left!());
ptr::copy_nonoverlapping(right!(), left!(), 1);
for _ in 1..count {
start_l = start_l.offset(1);
ptr::copy_nonoverlapping(left!(), right!(), 1);
start_r = start_r.offset(1);
ptr::copy_nonoverlapping(right!(), left!(), 1);
}
ptr::copy_nonoverlapping(&tmp, right!(), 1);
mem::forget(tmp);
start_l = start_l.offset(1);
start_r = start_r.offset(1);
}
}
if start_l == end_l {
l = unsafe { l.offset(block_l as isize) };
}
if start_r == end_r {
r = unsafe { r.offset(-(block_r as isize)) };
}
if is_done {
break;
}
}
if start_l < end_l {
debug_assert_eq!(width(l, r), block_l);
while start_l < end_l {
unsafe {
end_l = end_l.offset(-1);
ptr::swap(l.offset(*end_l as isize), r.offset(-1));
r = r.offset(-1);
}
}
width(v.as_mut_ptr(), r)
} else if start_r < end_r {
debug_assert_eq!(width(l, r), block_r);
while start_r < end_r {
unsafe {
end_r = end_r.offset(-1);
ptr::swap(l, r.offset(-(*end_r as isize) - 1));
l = l.offset(1);
}
}
width(v.as_mut_ptr(), l)
} else {
width(v.as_mut_ptr(), l)
}
}
fn partition<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> (usize, bool)
where
F: FnMut(&T, &T) -> bool,
{
let (mid, was_partitioned) = {
v.swap(0, pivot);
let (pivot, v) = v.split_at_mut(1);
let pivot = &mut pivot[0];
let tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
let _pivot_guard = CopyOnDrop { src: &*tmp, dest: pivot };
let pivot = &*tmp;
let mut l = 0;
let mut r = v.len();
unsafe {
while l < r && is_less(v.get_unchecked(l), pivot) {
l += 1;
}
while l < r && !is_less(v.get_unchecked(r - 1), pivot) {
r -= 1;
}
}
(l + partition_in_blocks(&mut v[l..r], pivot, is_less), l >= r)
};
v.swap(0, mid);
(mid, was_partitioned)
}
fn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> usize
where
F: FnMut(&T, &T) -> bool,
{
v.swap(0, pivot);
let (pivot, v) = v.split_at_mut(1);
let pivot = &mut pivot[0];
let tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
let _pivot_guard = CopyOnDrop { src: &*tmp, dest: pivot };
let pivot = &*tmp;
let mut l = 0;
let mut r = v.len();
loop {
unsafe {
while l < r && !is_less(pivot, v.get_unchecked(l)) {
l += 1;
}
while l < r && is_less(pivot, v.get_unchecked(r - 1)) {
r -= 1;
}
if l >= r {
break;
}
r -= 1;
let ptr = v.as_mut_ptr();
ptr::swap(ptr.add(l), ptr.add(r));
l += 1;
}
}
l + 1
}
fn choose_pivot<T, F>(v: &mut [T], is_less: &mut F) -> (usize, bool)
where
F: FnMut(&T, &T) -> bool,
{
const SHORTEST_MEDIAN_OF_MEDIANS: usize = 50;
const MAX_SWAPS: usize = 4 * 3;
let len = v.len();
let mut a = len / 4 * 1;
let mut b = len / 4 * 2;
let mut c = len / 4 * 3;
let mut swaps = 0;
if len >= 8 {
let mut sort2 = |a: &mut usize, b: &mut usize| unsafe {
if is_less(v.get_unchecked(*b), v.get_unchecked(*a)) {
ptr::swap(a, b);
swaps += 1;
}
};
let mut sort3 = |a: &mut usize, b: &mut usize, c: &mut usize| {
sort2(a, b);
sort2(b, c);
sort2(a, b);
};
if len >= SHORTEST_MEDIAN_OF_MEDIANS {
let mut sort_adjacent = |a: &mut usize| {
let tmp = *a;
sort3(&mut (tmp - 1), a, &mut (tmp + 1));
};
sort_adjacent(&mut a);
sort_adjacent(&mut b);
sort_adjacent(&mut c);
}
sort3(&mut a, &mut b, &mut c);
}
if swaps < MAX_SWAPS {
(b, swaps == 0)
} else {
v.reverse();
(len - 1 - b, true)
}
}
fn partition_at_index_loop<'a, T, F>(
mut v: &'a mut [T],
mut index: usize,
is_less: &mut F,
mut pred: Option<&'a T>,
) where
F: FnMut(&T, &T) -> bool,
{
loop {
const MAX_INSERTION: usize = 10;
if v.len() <= MAX_INSERTION {
insertion_sort(v, is_less);
return;
}
let (pivot, _) = choose_pivot(v, is_less);
if let Some(p) = pred {
if !is_less(p, &v[pivot]) {
let mid = partition_equal(v, pivot, is_less);
if mid > index {
return;
}
v = &mut v[mid..];
index = index - mid;
pred = None;
continue;
}
}
let (mid, _) = partition(v, pivot, is_less);
let (left, right) = v.split_at_mut(mid);
let (pivot, right) = right.split_at_mut(1);
let pivot = &pivot[0];
if mid < index {
v = right;
index = index - mid - 1;
pred = Some(pivot);
} else if mid > index {
v = left;
} else {
return;
}
}
}
fn partition_at_index<T, F>(
v: &mut [T],
index: usize,
mut is_less: F,
) -> (&mut [T], &mut T, &mut [T])
where
F: FnMut(&T, &T) -> bool,
{
use cmp::Ordering::Greater;
use cmp::Ordering::Less;
if index >= v.len() {
panic!("partition_at_index index {} greater than length of slice {}", index, v.len());
}
if mem::size_of::<T>() == 0 {
} else if index == v.len() - 1 {
let (max_index, _) = v
.iter()
.enumerate()
.max_by(|&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater })
.unwrap();
v.swap(max_index, index);
} else if index == 0 {
let (min_index, _) = v
.iter()
.enumerate()
.min_by(|&(_, x), &(_, y)| if is_less(x, y) { Less } else { Greater })
.unwrap();
v.swap(min_index, index);
} else {
partition_at_index_loop(v, index, &mut is_less, None);
}
let (left, right) = v.split_at_mut(index);
let (pivot, right) = right.split_at_mut(1);
let pivot = &mut pivot[0];
(left, pivot, right)
}
pub fn select_nth_unstable_by_key<T, K, F>(
slice:&mut [T],
index: usize,
mut f: F,
) -> (&mut [T], &mut T, &mut [T])
where
F: FnMut(&T) -> K,
K: Ord,
{
let mut g = |a: &T, b: &T| f(a).lt(&f(b));
partition_at_index(slice, index, &mut g)
}
}
mod rnd {
pub fn next()->usize{
static mut SEED:usize=88172645463325252;
unsafe{
SEED^=SEED<<7;
SEED^=SEED>>9;
SEED
}
}
}
use std::collections::{HashMap,HashSet};
use core::hash::BuildHasherDefault;
use core::hash::Hasher;
#[derive(Default)]
pub struct NopHasher{
hash:u64,
}
impl Hasher for NopHasher{
fn write(&mut self,_:&[u8]){
panic!();
}
#[inline]
fn write_u64(&mut self,n:u64){
self.hash=n;
}
#[inline]
fn finish(&self)->u64{
self.hash
}
}
pub type NopHashMap<K,V>=HashMap<K,V,BuildHasherDefault<NopHasher>>;
pub type NopHashSet<V>=HashSet<V,BuildHasherDefault<NopHasher>>;
Submission Info
Submission Time
2023-11-15 21:09:12+0900
Task
A - Pyramid Sorting
User
rhoo
Language
Rust (rustc 1.70.0)
Score
13640470
Code Size
32215 Byte
Status
AC
Exec Time
1979 ms
Memory
498320 KiB
Compile Error
warning: unused variable: `input`
--> src/main.rs:155:24
|
155 | fn raw_score(&self,input:&Input)->i64{
| ^^^^^ help: if this is intentional, prefix it with an underscore: `_input`
|
= note: `#[warn(unused_variables)]` on by default
warning: method `raw_score` is never used
--> src/main.rs:155:8
|
154 | impl Cand{
| --------- method in this implementation
155 | fn raw_score(&self,input:&Input)->i64{
| ^^^^^^^^^
|
= note: `#[warn(dead_code)]` on by default
warning: method `dfs` is never used
--> src/main.rs:281:8
|
206 | impl BeamSearch{
| --------------- method in this implementation
...
281 | fn dfs(&mut self,input:&Input,turn:usize,cands:&mut Vec<Vec<Cand>>,single:bool){
| ^^^
Judge Result
Set Name
test_ALL
Score / Max Score
13640470 / 15000000
Status
Set Name
Test Cases
test_ALL
test_0000.txt, test_0001.txt, test_0002.txt, test_0003.txt, test_0004.txt, test_0005.txt, test_0006.txt, test_0007.txt, test_0008.txt, test_0009.txt, test_0010.txt, test_0011.txt, test_0012.txt, test_0013.txt, test_0014.txt, test_0015.txt, test_0016.txt, test_0017.txt, test_0018.txt, test_0019.txt, test_0020.txt, test_0021.txt, test_0022.txt, test_0023.txt, test_0024.txt, test_0025.txt, test_0026.txt, test_0027.txt, test_0028.txt, test_0029.txt, test_0030.txt, test_0031.txt, test_0032.txt, test_0033.txt, test_0034.txt, test_0035.txt, test_0036.txt, test_0037.txt, test_0038.txt, test_0039.txt, test_0040.txt, test_0041.txt, test_0042.txt, test_0043.txt, test_0044.txt, test_0045.txt, test_0046.txt, test_0047.txt, test_0048.txt, test_0049.txt, test_0050.txt, test_0051.txt, test_0052.txt, test_0053.txt, test_0054.txt, test_0055.txt, test_0056.txt, test_0057.txt, test_0058.txt, test_0059.txt, test_0060.txt, test_0061.txt, test_0062.txt, test_0063.txt, test_0064.txt, test_0065.txt, test_0066.txt, test_0067.txt, test_0068.txt, test_0069.txt, test_0070.txt, test_0071.txt, test_0072.txt, test_0073.txt, test_0074.txt, test_0075.txt, test_0076.txt, test_0077.txt, test_0078.txt, test_0079.txt, test_0080.txt, test_0081.txt, test_0082.txt, test_0083.txt, test_0084.txt, test_0085.txt, test_0086.txt, test_0087.txt, test_0088.txt, test_0089.txt, test_0090.txt, test_0091.txt, test_0092.txt, test_0093.txt, test_0094.txt, test_0095.txt, test_0096.txt, test_0097.txt, test_0098.txt, test_0099.txt, test_0100.txt, test_0101.txt, test_0102.txt, test_0103.txt, test_0104.txt, test_0105.txt, test_0106.txt, test_0107.txt, test_0108.txt, test_0109.txt, test_0110.txt, test_0111.txt, test_0112.txt, test_0113.txt, test_0114.txt, test_0115.txt, test_0116.txt, test_0117.txt, test_0118.txt, test_0119.txt, test_0120.txt, test_0121.txt, test_0122.txt, test_0123.txt, test_0124.txt, test_0125.txt, test_0126.txt, test_0127.txt, test_0128.txt, test_0129.txt, test_0130.txt, test_0131.txt, test_0132.txt, test_0133.txt, test_0134.txt, test_0135.txt, test_0136.txt, test_0137.txt, test_0138.txt, test_0139.txt, test_0140.txt, test_0141.txt, test_0142.txt, test_0143.txt, test_0144.txt, test_0145.txt, test_0146.txt, test_0147.txt, test_0148.txt, test_0149.txt
Case Name
Status
Exec Time
Memory
test_0000.txt
AC
1974 ms
441652 KiB
test_0001.txt
AC
1977 ms
487976 KiB
test_0002.txt
AC
1975 ms
433992 KiB
test_0003.txt
AC
1973 ms
443016 KiB
test_0004.txt
AC
1977 ms
462344 KiB
test_0005.txt
AC
1977 ms
446012 KiB
test_0006.txt
AC
1973 ms
435512 KiB
test_0007.txt
AC
1974 ms
438604 KiB
test_0008.txt
AC
1979 ms
492836 KiB
test_0009.txt
AC
1979 ms
457832 KiB
test_0010.txt
AC
1974 ms
445116 KiB
test_0011.txt
AC
1972 ms
442464 KiB
test_0012.txt
AC
1974 ms
441916 KiB
test_0013.txt
AC
1975 ms
444980 KiB
test_0014.txt
AC
1973 ms
436832 KiB
test_0015.txt
AC
1972 ms
434612 KiB
test_0016.txt
AC
1972 ms
430804 KiB
test_0017.txt
AC
1972 ms
441600 KiB
test_0018.txt
AC
1974 ms
441340 KiB
test_0019.txt
AC
1972 ms
435484 KiB
test_0020.txt
AC
1972 ms
436864 KiB
test_0021.txt
AC
1973 ms
433576 KiB
test_0022.txt
AC
1974 ms
443904 KiB
test_0023.txt
AC
1975 ms
440776 KiB
test_0024.txt
AC
1975 ms
443568 KiB
test_0025.txt
AC
1974 ms
441340 KiB
test_0026.txt
AC
1975 ms
444388 KiB
test_0027.txt
AC
1974 ms
436280 KiB
test_0028.txt
AC
1974 ms
439092 KiB
test_0029.txt
AC
1974 ms
488308 KiB
test_0030.txt
AC
1972 ms
434156 KiB
test_0031.txt
AC
1975 ms
444876 KiB
test_0032.txt
AC
1972 ms
432248 KiB
test_0033.txt
AC
1973 ms
440508 KiB
test_0034.txt
AC
1977 ms
445084 KiB
test_0035.txt
AC
1973 ms
441972 KiB
test_0036.txt
AC
1974 ms
438444 KiB
test_0037.txt
AC
1972 ms
438592 KiB
test_0038.txt
AC
1973 ms
444640 KiB
test_0039.txt
AC
1977 ms
471956 KiB
test_0040.txt
AC
1978 ms
479504 KiB
test_0041.txt
AC
1975 ms
437888 KiB
test_0042.txt
AC
1974 ms
433924 KiB
test_0043.txt
AC
1973 ms
498320 KiB
test_0044.txt
AC
1976 ms
442512 KiB
test_0045.txt
AC
1974 ms
429152 KiB
test_0046.txt
AC
1973 ms
432548 KiB
test_0047.txt
AC
1972 ms
441312 KiB
test_0048.txt
AC
1975 ms
443072 KiB
test_0049.txt
AC
1977 ms
451764 KiB
test_0050.txt
AC
1975 ms
429072 KiB
test_0051.txt
AC
1978 ms
458388 KiB
test_0052.txt
AC
1974 ms
446500 KiB
test_0053.txt
AC
1975 ms
477868 KiB
test_0054.txt
AC
1975 ms
441848 KiB
test_0055.txt
AC
1975 ms
441836 KiB
test_0056.txt
AC
1974 ms
445344 KiB
test_0057.txt
AC
1973 ms
439108 KiB
test_0058.txt
AC
1974 ms
442876 KiB
test_0059.txt
AC
1976 ms
445008 KiB
test_0060.txt
AC
1973 ms
439900 KiB
test_0061.txt
AC
1972 ms
431352 KiB
test_0062.txt
AC
1973 ms
441152 KiB
test_0063.txt
AC
1972 ms
441712 KiB
test_0064.txt
AC
1976 ms
442388 KiB
test_0065.txt
AC
1976 ms
442268 KiB
test_0066.txt
AC
1975 ms
435132 KiB
test_0067.txt
AC
1975 ms
445340 KiB
test_0068.txt
AC
1976 ms
441360 KiB
test_0069.txt
AC
1973 ms
436856 KiB
test_0070.txt
AC
1974 ms
485084 KiB
test_0071.txt
AC
1975 ms
494644 KiB
test_0072.txt
AC
1973 ms
470140 KiB
test_0073.txt
AC
1972 ms
439628 KiB
test_0074.txt
AC
1973 ms
443140 KiB
test_0075.txt
AC
1974 ms
442136 KiB
test_0076.txt
AC
1976 ms
437728 KiB
test_0077.txt
AC
1973 ms
439192 KiB
test_0078.txt
AC
1975 ms
436912 KiB
test_0079.txt
AC
1974 ms
470612 KiB
test_0080.txt
AC
1972 ms
436916 KiB
test_0081.txt
AC
1973 ms
445248 KiB
test_0082.txt
AC
1975 ms
496908 KiB
test_0083.txt
AC
1973 ms
441088 KiB
test_0084.txt
AC
1972 ms
438736 KiB
test_0085.txt
AC
1975 ms
461624 KiB
test_0086.txt
AC
1973 ms
441236 KiB
test_0087.txt
AC
1974 ms
434588 KiB
test_0088.txt
AC
1972 ms
435956 KiB
test_0089.txt
AC
1977 ms
446956 KiB
test_0090.txt
AC
1976 ms
443484 KiB
test_0091.txt
AC
1972 ms
438568 KiB
test_0092.txt
AC
1975 ms
442568 KiB
test_0093.txt
AC
1973 ms
439544 KiB
test_0094.txt
AC
1975 ms
442920 KiB
test_0095.txt
AC
1977 ms
477860 KiB
test_0096.txt
AC
1976 ms
442732 KiB
test_0097.txt
AC
1973 ms
436564 KiB
test_0098.txt
AC
1975 ms
434052 KiB
test_0099.txt
AC
1976 ms
440012 KiB
test_0100.txt
AC
1976 ms
446844 KiB
test_0101.txt
AC
1972 ms
439236 KiB
test_0102.txt
AC
1973 ms
442108 KiB
test_0103.txt
AC
1973 ms
443420 KiB
test_0104.txt
AC
1972 ms
440696 KiB
test_0105.txt
AC
1976 ms
440672 KiB
test_0106.txt
AC
1973 ms
441740 KiB
test_0107.txt
AC
1974 ms
441744 KiB
test_0108.txt
AC
1976 ms
445268 KiB
test_0109.txt
AC
1975 ms
438728 KiB
test_0110.txt
AC
1975 ms
444660 KiB
test_0111.txt
AC
1973 ms
439280 KiB
test_0112.txt
AC
1973 ms
442036 KiB
test_0113.txt
AC
1974 ms
439588 KiB
test_0114.txt
AC
1975 ms
444536 KiB
test_0115.txt
AC
1973 ms
441184 KiB
test_0116.txt
AC
1974 ms
444144 KiB
test_0117.txt
AC
1974 ms
440144 KiB
test_0118.txt
AC
1975 ms
435980 KiB
test_0119.txt
AC
1977 ms
443620 KiB
test_0120.txt
AC
1972 ms
432116 KiB
test_0121.txt
AC
1976 ms
437792 KiB
test_0122.txt
AC
1974 ms
434528 KiB
test_0123.txt
AC
1972 ms
434784 KiB
test_0124.txt
AC
1975 ms
438932 KiB
test_0125.txt
AC
1974 ms
438684 KiB
test_0126.txt
AC
1973 ms
457360 KiB
test_0127.txt
AC
1976 ms
433816 KiB
test_0128.txt
AC
1973 ms
432236 KiB
test_0129.txt
AC
1976 ms
445252 KiB
test_0130.txt
AC
1977 ms
444392 KiB
test_0131.txt
AC
1976 ms
440448 KiB
test_0132.txt
AC
1975 ms
443620 KiB
test_0133.txt
AC
1977 ms
456136 KiB
test_0134.txt
AC
1971 ms
435184 KiB
test_0135.txt
AC
1974 ms
445784 KiB
test_0136.txt
AC
1976 ms
441548 KiB
test_0137.txt
AC
1976 ms
439008 KiB
test_0138.txt
AC
1975 ms
437372 KiB
test_0139.txt
AC
1973 ms
436464 KiB
test_0140.txt
AC
1975 ms
478620 KiB
test_0141.txt
AC
1975 ms
446464 KiB
test_0142.txt
AC
1972 ms
443248 KiB
test_0143.txt
AC
1974 ms
433736 KiB
test_0144.txt
AC
1973 ms
440968 KiB
test_0145.txt
AC
1975 ms
441044 KiB
test_0146.txt
AC
1971 ms
432748 KiB
test_0147.txt
AC
1973 ms
445528 KiB
test_0148.txt
AC
1973 ms
433476 KiB
test_0149.txt
AC
1973 ms
443264 KiB