// Templates and Snippets -> https://github.com/igeeeeee/template #ifdef ONLINE_JUDGE #pragma GCC optimize("Ofast") #pragma GCC optimize("unroll-loops") #endif #include #include using namespace std; using namespace atcoder; typedef long long ll; typedef unsigned long long ull; typedef long double ld; using i128 = __int128_t; using u128 = __uint128_t; ostream& operator<<(ostream& os, u128 x) {if (x >= 10) os << x / 10;return os << char('0' + x % 10);} ostream& operator<<(ostream& os, i128 x){if (x < 0){os << '-';return os << (-(u128)x);}return os << (u128)x;} #define rep(i, n) for (ll i = 0; i < (ll)(n); i++) #define rrep(i,start,end) for (ll i = start;i >= (ll)(end);i--) #define repn(i,end) for(ll i = 0; i <= (ll)(end); i++) #define reps(i,start,end) for(ll i = start; i < (ll)(end); i++) #define repsn(i,start,end) for(ll i = start; i <= (ll)(end); i++) #define each(p,a) for(auto &p:a) typedef vector vll; typedef vector> vpll; typedef vector>> vvpll; typedef vector> vvll; typedef vector>> vvvll; typedef pair pll; typedef pair pull; typedef tuple tpl3; typedef tuple tpl4; typedef tuple tpl5; typedef tuple tpl6; #define FI first #define SE second #define LL(...) ll __VA_ARGS__; input(__VA_ARGS__) #define LD(...) ld __VA_ARGS__; input(__VA_ARGS__) #define Str(...) string __VA_ARGS__; input(__VA_ARGS__) #define Ch(...) char __VA_ARGS__; input(__VA_ARGS__) #define all(a) (a).begin(),(a).end() #define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() ); #define sz(x) (ll)x.size() // << std::fixed << std::setprecision(10) const ll INF = 1LL << 60; const ld EPS = 1e-9; ll lceil(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b)+1;}else{return -((-a)/b);}} ll lfloor(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b);}else{return -((-a)/b)-1;}} inline ll positive_mod(ll a,ll m){return (a % m + m)%m;} inline ll popcnt(ull a){ return __builtin_popcountll(a);} //0indexed inline ll topbit(ll a){assert(a != 0);return 63 - __builtin_clzll(a);} inline ll smlbit(ll a){assert(a != 0);return __builtin_ctzll(a);} template bool chmin(T& a, T b){if(a > b){a = b;return true;}return false;} template bool chmax(T& a, T b){if(a < b){a = b;return true;}return false;} template std::istream &operator>>(std::istream&is,std::vector&v){for(T &in:v){is>>in;}return is;} template std::ostream &operator<<(std::ostream&os,const std::vector&v){for(auto it=std::begin(v);it!=std::end(v);){os<<*it<<((++it)!=std::end(v)?" ":"");}return os;} templatestd::ostream &operator<< (std::ostream &os, std::pair p){os << "{" << p.first << "," << p.second << "}";return os;} templatevoid input(T&... a){(cin >> ... >> a);} void print(){cout << endl;} templatevoid print(const T& a, const Ts&... b){cout << a;((cout << ' ' << b), ...);cout << endl;} template void pspace(const T& a){ cout << a << ' ';} void perr(){cerr << endl;} templatevoid perr(const T& a, const Ts&... b){cerr << a;((cerr << ' ' << b), ...);cerr << endl;} void yes(bool i = true){ return print(i?"yes":"no"); } void Yes(bool i = true){ return print(i?"Yes":"No"); } void YES(bool i = true){ return print(i?"YES":"NO"); } template vector &operator++(vector &v) {for(auto &e : v) e++;return v;} template vector operator++(vector &v, signed) {auto res = v;for(auto &e : v) e++;return res;} template vector &operator--(vector &v) {for(auto &e : v) e--;return v;} template vector operator--(vector &v, signed) {auto res = v;for(auto &e : v) e--;return res;} //grid探索用 vector _ta = {0,0,1,-1,1,1,-1,-1}; vector _yo = {1,-1,0,0,1,-1,1,-1}; bool isin(ll now_i,ll now_j,ll h,ll w){return (0<=now_i && now_i < h && 0 <= now_j && now_j < w);} ll lpow(ll x,ll n){ll ans = 1;while(n >0){if(n & 1)ans *= x;x *= x;n >>= 1;}return ans;} ll Modlpow(ll x,ll n,ll m){ll ans = 1;ll a = x%m;while(n >0){if(n & 1){ans *= a;ans%= m;}a *= a;a %= m;n >>= 1;}return ans;} const ll MOD9 = 998244353LL; const ll MOD10 = 1000000007LL; void solve(); #ifdef DEBUG void naive(); string run(void (*f)(), const string& input) {istringstream iss(input);ostringstream oss;auto* cinbuf = cin.rdbuf(iss.rdbuf());auto* coutbuf = cout.rdbuf(oss.rdbuf());cin.clear();f();cout.flush();cin.rdbuf(cinbuf);cout.rdbuf(coutbuf);cin.clear();return oss.str();} bool check(const string& input) { string ans = run(solve, input);istringstream acin(ans); string correct = run(naive, input);istringstream ccin(correct); // ll x;acin >> x;とかで使える(構築とかの確認用) if (ans == correct) return true;//末尾の空白まで完全一致 cerr << "========== INPUT ==========\n"; cerr << input; cerr << "========== EXPECTED =======\n"; cerr << correct; cerr << "========== ACTUAL =========\n"; cerr << ans; cerr << "===========================\n"; return false; } uint64_t seed = chrono::steady_clock::now().time_since_epoch().count(); mt19937_64 rng(seed); ll rnd(ll l, ll r){// l 以上 r 以下 return uniform_int_distribution(l, r)(rng); } void test(){ rep(tc,100000){ // ----- テストケース生成(文字列で!!) ----- string input; ll n = rnd(1,10); input += to_string(n); input += '\n'; // ----- 比較 ----- check(input); if ((tc+1) % 1000 == 0) { cerr << tc+1 << " cases passed\n"; } } } void naive(){//cinで受け取りcoutで出力でよい } #endif //双対セグ木 //fm(f,g)はgにfを作用させる(ACL準拠) // vefiry https://onlinejudge.u-aizu.ac.jp/solutions/problem/DSL_2_D/review/11750609/T21140031/C++23 template struct DualSegmentTree{ using FM = function; ll n,siz,height; FM fm; const M em;//Mの単位元 vector lazy; DualSegmentTree(ll _n,FM _fm,M _em):n(_n),fm(_fm),em(_em){ siz = 1; height = 0; while(siz < n){ siz <<= 1; ++height; } lazy.resize(2*siz,em); } DualSegmentTree(vector v,FM _fm,M _em): DualSegmentTree((ll)v.size(),_fm,_em){ for(ll i=0;i=1;i--){ push(p >> i); } lazy[p] = x; } M get(ll p){ assert(0 <= p && p < n); p += siz; for(ll i=height;i>=1;i--){ push(p >> i); } return lazy[p]; } void apply(ll p,M f){ assert(0 <= p && p < n); p += siz; for(ll i=height;i>=1;i--){ push(p >> i); } all_apply(p,f); } void apply(ll l,ll r,M f){ assert(0 <= l && l <= r && r <= n); if(l == r)return; l += siz; r += siz; for(ll i=height;i>=1;i--){ if(((l >> i) << i) != l)push(l >> i); if(((r >> i) << i) != r)push((r-1) >> i); } while(l < r){ if(l & 1)all_apply(l++,f); if(r & 1)all_apply(--r,f); l >>= 1; r >>= 1; } } }; void solve(){ LL(n); vll a(n);cin >> a; if(n == 1){ cout << max(1LL,a[0]) << endl; return ; } vll num(n+1); rep(i,n){ if(a[i]<=n)num[a[i]]++; else num[n]++; } auto op = [&](ll u,ll v){ if(u+v >= 1e9){ return (ll)1e9; } return u+v; }; ll ng = n+1;//条件を満たさない値 ll ok = 0;//条件を満たす値 auto f = [&](ll x)->bool { DualSegmentTree seg(n+1,op,0); vll b = num; ll need = 0; rep(i,x){ if(i==0){ need++; }else{ seg.apply(i,i+1,1); } } rrep(i,x-1,1){ //iを消して調節 ll v = seg.get(i); if(v <= b[i]){ b[i] -= v; }else{ v -= b[i]; b[i] = 0; seg.apply(0,i,v); } } need += seg.get(0); return need <= reduce(all(b)); }; while(abs(ok-ng) > 1){ ll mid = (ok + ng)/2; if(f(mid)){ ok = mid; }else{ ng = mid; } } cout << ok << endl; } int main(){ ios::sync_with_stdio(false);cin.tie(nullptr); #ifdef DEBUG test(); #else LL(t); while(t--) solve(); #endif }