結果
問題 | No.924 紲星 |
ユーザー | cureskol |
提出日時 | 2023-12-04 07:22:09 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 1,039 ms / 4,000 ms |
コード長 | 13,321 bytes |
コンパイル時間 | 2,880 ms |
コンパイル使用メモリ | 227,360 KB |
実行使用メモリ | 69,536 KB |
最終ジャッジ日時 | 2024-09-26 22:46:40 |
合計ジャッジ時間 | 13,705 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,248 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 4 ms
5,376 KB |
testcase_04 | AC | 3 ms
5,376 KB |
testcase_05 | AC | 5 ms
5,376 KB |
testcase_06 | AC | 4 ms
5,376 KB |
testcase_07 | AC | 3 ms
5,376 KB |
testcase_08 | AC | 1,023 ms
69,404 KB |
testcase_09 | AC | 1,039 ms
69,400 KB |
testcase_10 | AC | 1,013 ms
69,536 KB |
testcase_11 | AC | 996 ms
69,404 KB |
testcase_12 | AC | 999 ms
69,404 KB |
testcase_13 | AC | 403 ms
26,004 KB |
testcase_14 | AC | 344 ms
16,856 KB |
testcase_15 | AC | 339 ms
20,540 KB |
testcase_16 | AC | 531 ms
60,360 KB |
testcase_17 | AC | 555 ms
26,460 KB |
testcase_18 | AC | 2 ms
5,376 KB |
ソースコード
#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"; } }