結果

問題 No.924 紲星
ユーザー cureskolcureskol
提出日時 2023-12-04 07:22:09
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 1,157 ms / 4,000 ms
コード長 13,321 bytes
コンパイル時間 3,121 ms
コンパイル使用メモリ 228,592 KB
実行使用メモリ 69,528 KB
最終ジャッジ日時 2023-12-04 07:22:26
合計ジャッジ時間 15,842 ms
ジャッジサーバーID
(参考情報)
judge12 / judge11
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,676 KB
testcase_01 AC 2 ms
6,676 KB
testcase_02 AC 2 ms
6,676 KB
testcase_03 AC 3 ms
6,676 KB
testcase_04 AC 3 ms
6,676 KB
testcase_05 AC 3 ms
6,676 KB
testcase_06 AC 3 ms
6,676 KB
testcase_07 AC 2 ms
6,676 KB
testcase_08 AC 1,157 ms
69,528 KB
testcase_09 AC 1,146 ms
69,528 KB
testcase_10 AC 1,155 ms
69,528 KB
testcase_11 AC 1,145 ms
69,528 KB
testcase_12 AC 1,143 ms
69,528 KB
testcase_13 AC 444 ms
26,128 KB
testcase_14 AC 375 ms
16,980 KB
testcase_15 AC 367 ms
20,680 KB
testcase_16 AC 601 ms
60,484 KB
testcase_17 AC 592 ms
26,584 KB
testcase_18 AC 2 ms
6,676 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#line 1 "test/yukicoder/924.test.cpp"
#define PROBLEM "https://yukicoder.me/problems/no/924"
#include <bits/stdc++.h>
using namespace std;
#define REP(i, n) for (int i = 0; i < (n); i++)

#line 2 "library/algebra/group/Add.cpp"
template<typename X>
struct GroupAdd {
  using value_type = X;
  static constexpr X op(const X &x, const X &y) noexcept { return x + y; }
  static constexpr void Rchop(X&x, const X&y){ x+=y; }
  static constexpr void Lchop(const X&x, X&y){ y+=x; }
  static constexpr X inverse(const X &x) noexcept { return -x; }
  static constexpr X power(const X &x, long long n) noexcept { return X(n) * x; }
  static constexpr X unit() { return X(0); }
  static constexpr bool commute = true;
};
#line 2 "library/datastructure/FullyIndexableDictionary.cpp"
class FullyIndexableDictionary{
  int n,
      block; // 64個事に区切ったブロックの個数
  vector<unsigned long long> bit;
  vector<unsigned int> sum; // ブロック毎の累積和
  bool prepared;
public:
  FullyIndexableDictionary(){}
  FullyIndexableDictionary(int n)
    :n(n),block((n+63)>>6),bit(block,0),sum(block+1,0),prepared(false){}

  bool is_prepared(){ return prepared; }

  void set(int k){
    bit[k>>6]|=1ull<<(k&63);
    sum[(k>>6)+1]++;
  }
  void build(){ 
    assert(!prepared);
    prepared=true;
    for(int i=0;i<block;i++)sum[i+1]+=sum[i]; 
  }

  bool operator[](int k)const{
    return bool((bit[k>>6]>>(k&63))&1);
  }

  // [0,j) の合計
  int rank(int j,bool f=1){
    assert(prepared);
    int a=sum[j>>6]+__builtin_popcountll(bit[j>>6]&((1ull<<(j&63))-1));
    return (f?a:j-a);
  }
  // 0-indexed で k 番目の f の場所 
  int select(int k,bool f=1){
    assert(prepared);
    if(k<0 or rank(n,f)<=k)return -1;
    int l=0,r=n;
    while(r-l>1){
      int m=(l+r)>>1;
      (rank(m,f)>=k+1?r:l)=m;
    }
    return r-1;
  }
  // l以上で k 番目の f の場所
  int select(int k,bool f,int l){
    return select(rank(l,f)+k,f);
  }
};
#line 2 "library/util/Compress.cpp"
#define ALL_(v) v.begin(),v.end()
template<typename T,bool Sentinel=false>
class Compress{
  vector<T> v;
  bool prepared;
public:
  Compress():prepared(false){
    if constexpr(Sentinel){
      static_assert(std::numeric_limits<T>::is_specialized,"cannot use Sentinel");
      v={numeric_limits<T>::min(),numeric_limits<T>::max()};
    }
  }
  Compress(const vector<T>&w):v(w),prepared(false){
    if constexpr(Sentinel){
      static_assert(std::numeric_limits<T>::is_specialized,"cannot use Sentinel");
      v.push_back(numeric_limits<T>::min());
      v.push_back(numeric_limits<T>::max());
    }
    build();
  }
  
  void add(T a){ 
    assert(!prepared);
    v.push_back(a); 
  }
  void build(){
    assert(!prepared);
    prepared=true;
    sort(ALL_(v));
    v.erase(unique(ALL_(v)),v.end());
  }

  bool is_prepared()const{ return prepared; }

  int operator[](const T&a)const{
    assert(prepared);
    auto it=lower_bound(ALL_(v),a);
    assert(*it==a);
    return distance(v.begin(),it);
  }
  int geq(const T&a)const{
    assert(prepared);
    auto it=lower_bound(ALL_(v),a);
    return distance(v.begin(),it);
  }
  int gt(const T&a)const{
    assert(prepared);
    auto it=upper_bound(ALL_(v),a);
    return distance(v.begin(),it);
  }
  int leq(const T&a)const{
    assert(prepared);
    auto it=--upper_bound(ALL_(v),a);
    return distance(v.begin(),it);
  }
  int lt(const T&a)const{
    assert(prepared);
    auto it=--lower_bound(ALL_(v),a);
    return distance(v.begin(),it);
  }
  T r(int id)const{
    assert(prepared);
    return v[id];
  }
  bool exist(const T&a)const{
    assert(prepared);
    return (*lower_bound(ALL_(v),a))==a;
  }
  int size()const{return v.size();}
  T max()const{ return v.back(); }
  T min()const{ return v[0]; }

  friend ostream&operator<<(ostream&os, const Compress&C){ 
    for(int i=0;i<C.v.size();i++)os<<C.v[i]<<":"<<i<<" ";
    return os;
  }
};
#undef ALL_
#line 4 "library/datastructure/WaveletMatrix.cpp"
#define REP_(i,n) for(int i=0;i<(n);i++)
template<typename T,bool COMPRESS=true>
class WaveletMatrix{
protected:
  using U=conditional_t<COMPRESS,int,T>;
  static_assert(is_integral_v<U>,"Wavelet Matrix is only for integer");
  int n,memo,log;
  vector<FullyIndexableDictionary> mat;
  vector<int> zero_cnt;
  Compress<T,true> C;
  vector<T> data;

  constexpr U comp(const T&x)const{
    if constexpr(COMPRESS){ return C.geq(x); }
    else{ return x; }
  }
  constexpr T uncomp(const U&a){
    if constexpr(COMPRESS){ return C.r(a); }
    else{ return a; }
  }

  // 0-indexed で下から i bit 目
  inline bool low_bit (const U&a,int i)const{ return (a>>i)&1; }
  // 0-indexed で上から i bit 目
  inline bool high_bit(const U&a,int i)const{ return low_bit(a,log-i-1); }

  int nxt(int idx,int h,const U&a){
    // idx の位置に a があった場合上から h bit 目でどこに行くか
    bool bit=high_bit(a,h);
    return mat[h].rank(idx,bit)+(bit?zero_cnt[h]:0);
  }
public:
  WaveletMatrix(vector<T> v,int log_=0):n(v.size()),data(v),log(log_){
    vector<U> cv(n);
    if constexpr(COMPRESS){
      C=Compress<T,true>(v);
      for(int i=0;i<n;i++)cv[i]=C[v[i]];
      while(C.size()>=(1ull<<log))log++;
    }
    else{
      cv=v;
      T mx=0;
      for(const T&a:v){
        assert(a>=0);
        if(mx<a)mx=a;
      }
      while(mx>=(1ull<<log))log++;
    }
    mat.resize(log);
    zero_cnt.resize(log);
    vector<U> lv(n),rv(n);
    REP_(h,log){
      mat[h]=FullyIndexableDictionary(n);
      int l=0,r=0;
      REP_(i,n)
        if(high_bit(cv[i],h)){
          rv[r++]=cv[i];
          mat[h].set(i);
        }
        else
          lv[l++]=cv[i];
      zero_cnt[h]=l;
      mat[h].build();
      swap(lv,cv);
      REP_(i,r)cv[l+i]=rv[i];
    }
  }

  // [l,r) の x の個数
  int rank(int l,int r,const T&x){
    if constexpr(COMPRESS){
      if(!C.exist(x))return 0;
    }
    U a=comp(x);
    REP_(h,log){
      l=nxt(l,h,a);
      r=nxt(r,h,a);
    }
    memo=l;
    return r-l;
  }
  int rank(int r,const T&x){ return rank(x,0,r); }

  // k 番目の x の index
  int select(int k,const T&x){
    U a=comp(x);
    if(rank(a,n)<k)return -1;
    k+=memo;
    for(int h=log-1;h>=0;h--){
      bool bit=high_bit(a,h);
      if(bit)k-=zero_cnt[h];
      k=mat[h].select(k,bit);
    }
    return k;
  }
  
  // [l,r) で 0-indexed k 番目に大きい値
  T kth_largest(int l,int r,int k){
    if(k<0 or r-l<=k) return -1;
    U res=0;
    REP_(h,log){
      int L=mat[h].rank(l);
      int R=mat[h].rank(r);
      res<<=1;
      if(R-L>k){
        l=L+zero_cnt[h];
        r=R+zero_cnt[h];
        res++;
      }
      else{
        k-=R-L;
        l-=L;
        r-=R;
      }
    }
    return uncomp(res);
  }
  T kth_smallest(int l,int r,int k){ return kth_largest(l,r,r-l-k-1); }

  // [l,r) で x 未満の個数
  int range_freq(int l,int r,const T&upper){
    U a=comp(upper);
    int res=0;
    REP_(h,log){
      if(high_bit(a,h)){
        int L=mat[h].rank(l,0),R=mat[h].rank(r,0);
        res+=R-L;
      }
      l=nxt(l,h,a);
      r=nxt(r,h,a);
    }
    return res;
  }
  // [l,r) で [lower,upper) の個数
  int range_freq(int l,int r,const T&lower,const T&upper){
    return range_freq(l,r,upper)-range_freq(l,r,lower);
  }

  optional<T> lt(int l,int r,const T&x){
    int cnt=range_freq(l,r,x);
    if(cnt)return kth_smallest(l,r,cnt-1);
    return nullopt;
  }
  optional<T> leq(int l,int r,const T&x){
    if(rank(l,r,x))return x;
    return lt(l,r,x);
  }
  optional<T> geq(int l,int r,const T&x){
    int cnt=r-l-range_freq(l,r,x);
    if(cnt)return kth_largest(l,r,cnt-1);
    return nullopt;
  }
  optional<T> gt(int l,int r,const T&x){
    T y;
    if constexpr(COMPRESS){ y=C.r(C.gt(x)); }
    else{ y=x+1; }
    return geq(l,r,y);
  }

  // セグ木などを載せる時用
  // BIT は専用のライブラリを作ってあるが、一応抽象化も持っておく
  // 構築したものを返してるので遅そう
  int height()const{ return log; }
  vector<int> points(int idx){
    vector<int> res(log);
    U a=comp(data[idx]);
    REP_(h,log){
      idx=nxt(idx,h,a);
      res[h]=idx;
    }
    return res;
  }
  vector<tuple<int,int,int>> intervals(int l,int r,const T&upper){
    vector<tuple<int,int,int>> res;
    U a=comp(upper);
    REP_(h,log){
      if(high_bit(a,h)){
        int L=mat[h].rank(l,0),R=mat[h].rank(r,0);
        res.emplace_back(h,L,R);
      }
      l=nxt(l,h,a);
      r=nxt(r,h,a);
    }
    return res;
  }
  vector<tuple<int,int,int>> kth_largest_intervals(int l,int r,int k){
    assert(0<=k and k<r-l);
    vector<tuple<int,int,int>> res;
    REP_(h,log){
      int L=mat[h].rank(l);
      int R=mat[h].rank(r);
      if(R-L>k){
        l=L+zero_cnt[h];
        r=R+zero_cnt[h];
      }
      else{
        res.emplace_back(h,L+zero_cnt[h],R+zero_cnt[h]);
        k-=R-L;
        l-=L;
        r-=R;
      }
    }
    return res;
  }
  vector<tuple<int,int,int>> kth_smallest_intervals(int l,int r,int k){
    return kth_largest_intervals(l,r,r-l-k-1);
  }
};
#undef REP_
#line 3 "library/datastructure/FenwickTree.cpp"
template<typename AbelGroup=GroupAdd<long long>>
class FenwickTree{
  using G=AbelGroup;
  using T=typename G::value_type;
  int n;
  vector<T> dat,raw;
public:
  FenwickTree(){
    assert(G::commute);
  }
  FenwickTree(int n):n(n){
    assert(G::commute);
    dat=raw=vector<T>(n,G::unit());
  }
  FenwickTree(const vector<T>&v):n(v.size()),raw(v),dat(v){
    assert(G::commute);
    for(int i=1;i<=n;i++){
      int j=i+(i&-i);
      if(j<=n)G::Rchop(dat[j-1],dat[i-1]);
    }
  }

  T operator[](int k)const{ return raw[k]; }
  T get(int k)const{ return raw[k]; }

  void multiply(int k,const T&x){
    G::Rchop(raw[k],x);
    for(++k;k<=n;k+=k&-k)G::Rchop(dat[k-1],x);
  }
  void add(int k,const T&x){ multiply(k,x); }
  void set(int k,const T&x){ multiply(k,G::op(x,G::inverse(raw[k]))); }

  T prod(int k)const{
    T res=G::unit();
    while(k>0){
      G::Rchop(res, dat[k-1]);
      k -= k&-k;
    }
    return res;
  }
  T sum(int k)const{ return prod(k); }
  T prod(int L,int R)const{
    T pos=G::unit();
    while(L<R){
      G::Rchop(pos,dat[R-1]);
      R -= R&-R;
    }
    T neg=G::unit();
    while(R<L){
      G::Rchop(neg,dat[L-1]);
      L -= L&-L;
    }
    return G::op(pos,G::inverse(neg));
  }
  T sum(int L,int R)const{ return prod(L,R); }

  template<class F>
  int max_right(const F check)const{
    assert(check(G::unit()));
    int r=0;
    T sum=G::unit();
    int k=1;
    while(2*k<=n)k<<=1;
    while(k){
      if(r+k-1<dat.size())
        if(check(G::op(sum,dat[r+k-1]))){
          G::Rchop(sum,dat[r+k-1]);
          r += k;
        }
      k >>= 1;
    }
    return r;
  }

  int kth(T k)const{
    return max_right( [&k](T x){ return x<=k; } );
  }
};
#line 4 "library/datastructure/GroupWaveletMatrix.cpp"
#define REP_(i,n) for(int i=0;i<(n);i++)
template<typename T,typename AbelGroup>
class GroupWaveletMatrix:WaveletMatrix<T,true>{
  using super=WaveletMatrix<T,true>;
  using super::log,super::n,super::nxt,super::comp,super::data,super::high_bit,super::mat,super::zero_cnt;
  using U=typename super::U;
  using FT=FenwickTree<AbelGroup>;
  using S=typename AbelGroup::value_type;
  vector<FT> ft;
public:
  using super::rank,super::select,super::kth_largest,super::kth_smallest,super::range_freq,super::lt,super::leq,super::gt,super::geq;
  GroupWaveletMatrix(vector<T> v):super::WaveletMatrix(v){
    ft.resize(log);
    for(auto&p:ft)p=FT(n);
  }
  GroupWaveletMatrix(vector<T> v,const vector<S>&w):GroupWaveletMatrix(v){
    for(int i=0;i<n;i++)add(i,w[i]);
  }
  void add(int idx,const S&val){
    U a=comp(data[idx]);
    REP_(h,log){
      idx=nxt(idx,h,a);
      ft[h].add(idx,val);
    }
  }
  S sum(int l,int r,const T&upper){
    U a=comp(upper);
    S res=AbelGroup::unit();
    REP_(h,log){
      if(high_bit(a,h)){
        int L=mat[h].rank(l,0),R=mat[h].rank(r,0);
        AbelGroup::Rchop(res,ft[h].sum(L,R));
      }
      l=nxt(l,h,a);
      r=nxt(r,h,a);
    }
    return res;
  }
  S sum(int l,int r,const T&lower,const T&upper){
    return AbelGroup::op(sum(l,r,upper),AbelGroup::inverse(sum(l,r,lower)));
  }
  S kth_largest_sum(int l,int r,int k){
    assert(0<=k and k<r-l);
    S res=AbelGroup::unit();
    REP_(h,log){
      int L=mat[h].rank(l);
      int R=mat[h].rank(r);
      if(R-L>k){
        l=L+zero_cnt[h];
        r=R+zero_cnt[h];
      }
      else{
        AbelGroup::Rchop(res,ft[h].sum(L+zero_cnt[h],R+zero_cnt[h]));
        k-=R-L;
        l-=L;
        r-=R;
      }
    }
    return res;
  }
};
#undef REP_
#line 8 "test/yukicoder/924.test.cpp"

using ll = long long;
constexpr ll LINF = 1e18;

int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);

  int n, q;
  cin >> n >> q;
  vector<ll> v(n);
  for (int i = 0; i < n; i++)
    cin >> v[i];
  GroupWaveletMatrix<ll, GroupAdd<ll>> WM(v, v);

  while (q--) {
    int l, r;
    cin >> l >> r;
    l--;
    int k = (r - l) / 2; // 0-indexed 小さい方から k 番目の値を x にする
    ll x = WM.kth_smallest(l, r, k);
    ll res = 0;
    // x 未満
    ll cnt1 = WM.range_freq(l, r, x);
    res += x * cnt1 - WM.sum(l, r, x);
    // x 以上
    ll cnt2 = WM.range_freq(l, r, x, LINF);
    res += WM.sum(l, r, x, LINF) - x * cnt2;

    cout << res << "\n";
  }
}
0