結果
| 問題 |
No.919 You Are A Project Manager
|
| コンテスト | |
| ユーザー |
cureskol
|
| 提出日時 | 2022-12-12 18:53:02 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 114 ms / 3,000 ms |
| コード長 | 4,110 bytes |
| コンパイル時間 | 2,205 ms |
| コンパイル使用メモリ | 203,664 KB |
| 最終ジャッジ日時 | 2025-02-09 10:20:13 |
|
ジャッジサーバーID (参考情報) |
judge4 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 55 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
#line 2 "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 3 "datastructure/WaveletMatrix.cpp"
#define REP_(i,n) for(int i=0;i<(n);i++)
template<typename T,int LOG>
class WaveletMatrix{
int n;
array<FullyIndexableDictionary,LOG> mat;
array<int,LOG> zero_cnt;
int memo;
// 0-indexed で下から i bit 目
static constexpr bool low_bit (const T&a,int i){ return (a>>i)&1; }
// 0-indexed で上から i bit 目
static constexpr bool high_bit(const T&a,int i){ return low_bit(a,LOG-i-1); }
int nxt(int idx,int h,const T&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):n(v.size()){
for(const T&p:v)
assert(0<=p and p<(1ull<<LOG));
vector<T> lv(n),rv(n);
REP_(h,LOG){
mat[h]=FullyIndexableDictionary(n);
int l=0,r=0;
REP_(i,n)
if(high_bit(v[i],h)){
rv[r++]=v[i];
mat[h].set(i);
}
else
lv[l++]=v[i];
zero_cnt[h]=l;
mat[h].build();
swap(lv,v);
REP_(i,r)v[l+i]=rv[i];
}
}
// [l,r) の a の個数
int rank(T a,int l,int r){
REP_(h,LOG){
l=nxt(l,h,a);
r=nxt(r,h,a);
}
memo=l;
return r-l;
}
int rank(T a,int r){ return rank(a,0,r); }
// k 番目の a の index
int select(T a,int k){
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;
T 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 res;
}
T kth_smallest(int l,int r,int k){ return kth_largest(l,r,r-l-k-1); }
};
#undef REP_
using ll=long long;
const ll INF=1000'000'000;
void chmax(ll&a,ll b){ a=max(a,b); }
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;cin>>n;
vector<ll> v(n);
for(int i=0;i<n;i++){
cin>>v[i];
v[i]+=INF;
}
WaveletMatrix<ll,32> WM(v);
ll ans=0;
for(int k=1;k<=n;k++){
vector<ll> pre{0};
for(int i=0;i+k<=n;i+=k){
// [i,i+k) の中央値を求める
ll b=WM.kth_smallest(i,i+k,(k-1)/2);
pre.push_back(pre.back()+(b-INF)*k);
}
for(int i=1;i<pre.size();i++)chmax(pre[i],pre[i-1]);
chmax(ans,pre.back());
ll sum=0;
for(int r=n,id=pre.size()-2;r-k>=0;r-=k,id--){
ll b=WM.kth_smallest(r-k,r,(k-1)/2);
sum+=(b-INF)*k;
chmax(ans,pre[id]+sum);
}
}
cout<<ans<<endl;
}
cureskol