제출 #1315495

#제출 시각아이디문제언어결과실행 시간메모리
1315495idk_anything_i_guess말 (IOI15_horses)C++20
37 / 100
579 ms40688 KiB
// compile with -O2 -std=gnu++17 #include <bits/stdc++.h> using namespace std; using ll = long long; using pii = pair<int,int>; const ll mod = 1000000007LL; const long double THRESH = 1e9L; // threshold used in original code // fast powmod ll modpow(ll a, ll e) { ll r = 1 % mod; a %= mod; while (e) { if (e & 1) r = (r * a) % mod; a = (a * a) % mod; e >>= 1; } return r; } ll invmod(ll a){ return modpow((a%mod+mod)%mod, mod-2); } // Fenwick (BIT) for multiplicative prefix product modulo `mod`. struct Fenwick { int n; vector<ll> bit; Fenwick() : n(0) {} Fenwick(int _n){ init(_n); } void init(int _n){ n = _n; bit.assign(n+1, 1); } // multiply index i by val (mod) void mul_point(int i, ll val){ while(i <= n){ bit[i] = (bit[i] * val) % mod; i += i & -i; } } // prefix product 1..i ll prefix(int i) const { ll res = 1; while(i > 0){ res = (res * bit[i]) % mod; i -= i & -i; } return res; } // range product l..r ll range(int l,int r) const { if(l>r) return 1; ll a = prefix(r); ll b = prefix(l-1); return (a * invmod(b)) % mod; } }; // iterative segment tree for range max, point update struct SegMax { int n; int size; vector<int> seg; SegMax(){} void init(int _n){ n = _n; size = 1; while(size < n) size <<= 1; seg.assign(2*size, 0); } void set_point(int pos, int val){ // pos in [1..n] int i = pos - 1 + size; seg[i] = val; for(i >>= 1; i; i >>= 1) seg[i] = max(seg[2*i], seg[2*i+1]); } int range_max(int l,int r){ // inclusive, 1..n if(l>r) return 0; int L = l - 1 + size, R = r - 1 + size; int ans = 0; while(L <= R){ if(L & 1) ans = max(ans, seg[L++]); if(!(R & 1)) ans = max(ans, seg[R--]); L >>= 1; R >>= 1; } return ans; } }; static int N_global = 0; static vector<int> Xarr, Yarr; // 0..N static Fenwick fen; static SegMax segy; static set<int> special; // indices i where X[i] > 1, plus sentinel 0 static const ll SENTINEL_X0 = 1000000000LL; // same as 1e9 from your code // get segment end for special index s: next(s) - 1, or N_global if none inline int seg_end_of(int s){ auto it = special.upper_bound(s); if(it == special.end()) return N_global; return (*it) - 1; } // compute answer following the same logic as original code int compute_answer(){ // collect suffix of special indices starting from largest until product >= 1e9 deque<pair<int,int>> a; // (startIndex, endIndex) __int128 tem = 1; for(auto it = special.rbegin(); it != special.rend(); ++it){ int s = *it; int r = seg_end_of(s); a.emplace_front(s, r); tem *= (__int128) Xarr[s]; if(tem >= (__int128)1000000000LL) break; } // special-case matching original: // if the first picked segment starts at 0 (sentinel), temporarily remove it from consideration long long ans1 = 0; __int128 intem = tem; if(!a.empty() && a.front().first == 0){ // divide out sentinel contribution tem /= (__int128)Xarr[0]; // Xarr[0] = 1e9 sentinel intem /= (__int128)Xarr[0]; if(tem < (__int128)1000000000LL){ // ans1 = ry.mx(1,n) in your code ans1 = segy.range_max(1, N_global); } // remove sentinel from deque (original code popped it) a.pop_front(); } if(a.empty()){ // nothing chosen: return overall max y return segy.range_max(1, N_global) % (int)mod; } // compute ma = max over selected segments of (product_of_selected_specials_prefix * maxY_in_segment) __int128 prodprefix = 1; __int128 ma128 = 0; for(auto &pr : a){ int s = pr.first, r = pr.second; prodprefix *= (__int128) Xarr[s]; int localMaxY = 0; if(s == 0){ // should not happen here (we popped sentinel); but safe fallback localMaxY = segy.range_max(1, N_global); } else { localMaxY = segy.range_max(s, r); } __int128 candidate = prodprefix * (__int128)localMaxY; if(candidate > ma128) ma128 = candidate; } // multiply by product of x's on left of first selected special: rx.mul(1, a[0].fi-1) int firstSpecial = a.front().first; ll leftProdMod = fen.range(1, max(0, firstSpecial - 1)); // incorporate ans1 if applicable (original logic took max with ma after mod) ll ma_mod = (ll)( ( (long long)(ma128 % (__int128)mod) ) % mod ); if(intem < (__int128)1000000000LL){ ma_mod = max(ma_mod, (ll)ans1); // ans1 already fits in int } ll result = (ma_mod * leftProdMod) % mod; return (int) result; } // API functions (match original names/behaviour) int init(int N, int X[], int Y[]){ N_global = N; Xarr.assign(N+1, 1); Yarr.assign(N+1, 0); // index 0 sentinel Xarr[0] = (int)SENTINEL_X0; // Fenwick only stores indices 1..N fen.init(N); segy.init(N); special.clear(); special.insert(0); // sentinel // fill arrays and structures for(int i=1;i<=N;i++){ Xarr[i] = X[i-1]; Yarr[i] = Y[i-1]; // fenwick multiply by X[i] fen.mul_point(i, (Xarr[i] % mod + mod) % mod); // segtree for Y segy.set_point(i, Yarr[i]); if(Xarr[i] > 1) special.insert(i); } // answer return compute_answer(); } int updateX(int idx0, int v){ // idx0 is 0-based int i = idx0 + 1; int old = Xarr[i]; if(old == v) return compute_answer(); // update fenwick: multiply index i by (v * inv(old)) ll mulval = ( (v % mod + mod) % mod ) * invmod( (old % mod + mod) % mod ) % mod; fen.mul_point(i, mulval); Xarr[i] = v; // maintain special set bool wasSpecial = (old > 1); bool nowSpecial = (v > 1); if(wasSpecial && !nowSpecial){ special.erase(i); } else if(!wasSpecial && nowSpecial){ special.insert(i); } return compute_answer(); } int updateY(int idx0, int v){ int i = idx0 + 1; Yarr[i] = v; segy.set_point(i, v); return compute_answer(); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...