結果

問題 No.3122 Median of Medians of Division
ユーザー rhoo
提出日時 2025-04-19 13:19:54
言語 Rust
(1.83.0 + proconio)
結果
RE  
実行時間 -
コード長 6,294 bytes
コンパイル時間 13,777 ms
コンパイル使用メモリ 399,168 KB
実行使用メモリ 32,648 KB
最終ジャッジ日時 2025-04-19 13:20:13
合計ジャッジ時間 15,824 ms
ジャッジサーバーID
(参考情報)
judge2 / judge5
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample RE * 1
other RE * 40
権限があれば一括ダウンロードができます
コンパイルメッセージ
warning: unreachable statement
  --> src/main.rs:78:5
   |
76 |     panic!();
   |     -------- any code following this expression is unreachable
77 |
78 |     let mut seq=R::new(0,seq_ps);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement
   |
   = note: `#[warn(unreachable_code)]` on by default

ソースコード

diff #

#![allow(unused_imports,non_snake_case,dead_code)]
use std::{cmp::Reverse as Rev,collections::*,iter::*};
use proconio::{marker::*,*};


#[fastout]
fn main(){
    input!{
        n:usize,
        q:usize,
        a:[usize;n],
    }

    let mut qs=vec![];
    for _ in 0..q{
        input!{
            t:usize,
        }

        if t==1{
            // change
            input!{
                i:Usize1,
                x:usize,
            }

            let new=Q{
                t:Change,i,x,
                l:!0,r:!0,
            };
            qs.push(new);

        } else{
            // get
            input!{
                l:Usize1,
                r:usize,
            }

            let new=Q{
                t:Get,i:!0,x:!0,
                l,r,
            };
            qs.push(new);

        }
    }

    let mut seq_ps=vec![];
    let mut adj_ps=vec![];
    {
        let mut a=a.clone();
        for i in 0..n{
            seq_ps.push((i,a[i]));
            if 1<=i{
                adj_ps.push((i-1,a[i-1].max(a[i])));
            }
        }
        
        for &q in &qs{
            if q.t!=Change{
                continue;
            }
            a[q.i]=q.x;
            seq_ps.push((q.i,q.x));

            if 1<=q.i{
                adj_ps.push((q.i-1,a[q.i-1].max(a[q.i])));
            }
            if q.i+1<a.len(){
                adj_ps.push((q.i,a[q.i].max(a[q.i+1])));
            }
        }
    }

    panic!();

    let mut seq=R::new(0,seq_ps);
    let mut adj=R::new(0,adj_ps);
    let mut a=a;

    let get=|re:&R,l:usize,r:usize,a:usize|->i64{
        assert!(0<=a as i64);
        let right=if (r as i64)<0{
            0
        } else{
            re.find(r,a)
        };
        let left=if (l as i64)<0{
            0
        } else{
            re.find(l,a)
        };
        assert!(left<=right);
        right-left
    };

    for i in 0..n{
        seq.add(i,a[i],1);
        if 1<=i{
            adj.add(i-1,a[i-1].max(a[i]),1);
        }
    }

    for &q in &qs{
        if q.t==Change{
            let i=q.i;
            let x=q.x;

            seq.add(i,a[i],-1);
            seq.add(i,x,1);
            if 1<=i{
                adj.add(i-1,a[i-1].max(a[i]),-1);
                adj.add(i-1,a[i-1].max(x),1);
            }
            if i+1<a.len(){
                adj.add(i,a[i].max(a[i+1]),-1);
                adj.add(i,x.max(a[i+1]),1);
            }
            
            a[i]=x;
        } else{
            let l=q.l;
            let r=q.r;

            let mut ok=0;
            let mut ng=1e9 as usize+1;
            // eprintln!("Query: {:?}",&a[l..r]);

            while ng-ok>1{
                let m=(ok+ng)/2;

                let z=get(&adj,l-1,r-2,m-1); // [l,r)で隣接する2つがどっちもm未満である場所の数
                // assert!(z==verify_z(&a[l..r],m));

                let y=get(&seq,l-1,r-1,m-1); // [l,r)でm未満の場所の数
                // assert!(y==verify_y(&a[l..r],m));

                let x=y-z; // // [l,r)でk未満の連続部分列の個数
                // eprintln!("{m} : {} {} {}",x,y,z);

                if x as usize<=(r-l-y as usize+x as usize-1)/2{
                    ok=m;
                } else{
                    ng=m;
                }
            }
            // eprintln!();

            println!("{ok}");
        }
    }
}


fn verify_z(a:&[usize],m:usize)->i64{
    let mut ret=0;
    for i in 1..a.len(){
        ret+=(a[i-1].max(a[i])<m) as i64;
    }
    ret
}


fn verify_y(a:&[usize],m:usize)->i64{
    let mut ret=0;
    for i in 0..a.len(){
        ret+=(a[i]<m) as i64;
    }
    ret
}


#[derive(Clone,Copy,PartialEq,Eq)]
enum T{
    Change,Get,
}
use T::*;


#[derive(Clone,Copy)]
struct Q{
    t:T,
    i:usize,
    x:usize,
    l:usize,
    r:usize,
}


type R=RectangleSum<usize,i64>;



// 窃盗:https://judge.yosupo.jp/submission/33203
// ありがとうございます...


struct RectangleSum<Index, Weight> {
    point: Vec<(Index, Index)>,
    row: Vec<Index>,
    col: Vec<Vec<Index>>,
    bit: Vec<Vec<Weight>>,
    zero: Weight,
}

impl<Index, Weight> RectangleSum<Index, Weight>
where
    Index: Ord + Copy,
    Weight: std::ops::Add<Output = Weight> + Copy,
{
    fn new(zero: Weight, point: Vec<(Index, Index)>) -> Self {
        let mut r=RectangleSum {
            point,
            row: vec![],
            col: vec![],
            bit: vec![],
            zero: zero,
        };
        r.build();
        r
    }
    fn build(&mut self) {
        let mut row: Vec<_> = self.point.iter().map(|p| p.0).collect();
        row.sort();
        row.dedup();
        let mut col = vec![vec![]; row.len() + 1];
        for &(x, y) in self.point.iter() {
            let mut k = row.binary_search(&x).unwrap() + 1;
            while let Some(a) = col.get_mut(k) {
                a.push(y);
                k += k & (!k + 1);
            }
        }
        let mut bit = vec![vec![]; row.len() + 1];
        for (bit, col) in bit.iter_mut().zip(col.iter_mut()).skip(1) {
            col.sort();
            col.dedup();
            bit.resize(col.len() + 1, self.zero);
        }
        self.row = row;
        self.col = col;
        self.bit = bit;
    }
    fn add(&mut self, x: Index, y: Index, w: Weight) {
        let mut x = self.row.binary_search(&x).unwrap() + 1;
        while let Some(bit) = self.bit.get_mut(x) {
            let mut y = self.col[x].binary_search(&y).unwrap() + 1;
            while let Some(v) = bit.get_mut(y) {
                *v = *v + w;
                y += y & (!y + 1);
            }
            x += x & (!x + 1);
        }
    }
    // (-inf, x] * (-inf * y] の和
    fn find(&self, x: Index, y: Index) -> Weight {
        let upper_bound = |x: &[Index], v: &Index| -> usize {
            use std::cmp::Ordering::Less;
            x.binary_search_by(|p| p.cmp(v).then(Less)).unwrap_err()
        };
        let mut x = upper_bound(&self.row, &x);
        let mut ans = self.zero;
        while x > 0 {
            let mut y = upper_bound(&self.col[x], &y);
            let bit = &self.bit[x];
            while y > 0 {
                ans = ans + bit[y];
                y -= y & (!y + 1);
            }
            x -= x & (!x + 1);
        }
        ans
    }
}
0