結果
| 問題 |
No.924 紲星
|
| コンテスト | |
| ユーザー |
cureskol
|
| 提出日時 | 2023-12-04 07:22:09 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 1,121 ms / 4,000 ms |
| コード長 | 13,321 bytes |
| コンパイル時間 | 2,788 ms |
| コンパイル使用メモリ | 218,056 KB |
| 最終ジャッジ日時 | 2025-02-18 07:08:23 |
|
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 16 |
ソースコード
#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";
}
}
cureskol