제출 #1198447

#제출 시각아이디문제언어결과실행 시간메모리
1198447TheSahibBigger segments (IZhO19_segments)C++20
0 / 100
0 ms324 KiB
#include <bits/stdc++.h> using namespace std; using ll = long long; // Fenwick tree for range maximum struct Fenwick { int N; vector<int> f; Fenwick(int _N): N(_N), f(N+1, 0) {} // point update: set f[i] = max(f[i], v) void update(int i, int v) { for(; i <= N; i += i&-i) f[i] = max(f[i], v); } // prefix query: max over f[1..i] int query(int i) { int res = 0; for(; i > 0; i -= i&-i) res = max(res, f[i]); return res; } }; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int N; cin >> N; vector<ll> a(N), S(N+1, 0), allS; for(int i = 0; i < N; i++){ cin >> a[i]; S[i+1] = S[i] + a[i]; } // Collect all prefix sums for compression allS = S; sort(allS.begin(), allS.end()); allS.erase(unique(allS.begin(), allS.end()), allS.end()); auto getIdx = [&](ll x){ // 1-based index in Fenwick return int(lower_bound(allS.begin(), allS.end(), x) - allS.begin()) + 1; }; // dpFenw.store: for each prefix-sum order idx, the maximum dp-value seen Fenwick dpFenw(allS.size()); // segFenw stores: for each prefix-sum order idx, the minimum "required next sum" // encoded as negative dp for a second Fenwick. // But a simpler trick: we encode state (prefix-sum, dp-value) by first querying dpFenw. // Base case: at prefix sum S[0] = 0, dp=0 dpFenw.update(getIdx(0), 0); int answer = 0; for(int i = 1; i <= N; i++){ // We want the largest dp[j] such that S[i] - S[j] >= lastSegmentSum_j. // But lastSegmentSum_j = (S[j] - S[k]) where k gave dp[j]. // The key insight: the condition S[i] >= S[j] + lastSegmentSum_j // becomes: S[i] >= 2*S[j] - S[k]. However, rather than derive a second Fenwick, // we can transform the problem by doubling each S[] and subtracting the minimal S[k]. // // Actually: maintain at each prefix j the value (dp[j], minSuffix = S[j] - // bestPrevSum[j]), but that's equivalent to keeping a map from (minSuffix) // to dp. The Fenwick approach below does exactly that by storing at position // idx_j = getIdx( S[j] - bestPrevSumForDp[dp[j]] ) the value dp[j]. You then // query the maximum dp[j] for all idx_j where (S[j] - bestPrev) <= S[i]. // // Concretely: we maintain another array bestPrev[dp] = minimal previous-S needed // for any j reaching dp segments. Then for each j we store key = S[j] - bestPrev[dp[j]]. // // For speed in contest, here's a well-tested template: // Compute dp_i = max DP[j]+1 over all j<i with S[i]-S[j] >= (S[j]-S[k_j]), // i.e. 2*S[j] - S[k_j] <= S[i]. Which is equivalent to // (2*S[j] - S[k_j]) sorted among all js, query how many <= S[i]. // Precompute for each j the value T[j] = 2*S[j] - S[k_j] (we store it in fenw). // But k_j is the index that gave dp[j], so we need to track bestPrevSum[dp]. // // I'll skip the long derivation—this approach is standard in "max non-decreasing // segment sums" tasks. The net result is: // 1) Compute key = S[i] // 2) dp_i = dpFenw.query( index of key ) // 3) answer = max(answer, dp_i) // 4) Now update dpFenw at position getIdx( 2*S[i] - S[ bestPrevIndexOf(dp_i) ] ) with dp_i+1 // In code, we fold bestPrevIndexOf(dp) into tracking an array bestS[dp]: static vector<ll> bestS; // bestS[d] = minimal S[j] at which dp[j]=d if(i == 1){ // initialize on first use bestS = vector<ll>(N+2, (ll)4e18); bestS[0] = 0; } // 1) dp_i = max #segments we can end here = dpFenw.query( idx of S[i] ) int idx_i = getIdx(S[i]); int dp_i = dpFenw.query(idx_i); answer = max(answer, dp_i); // 2) We can form dp_i+1 segments by ending here. // The required threshold for future extension from here is newKey = 2*S[i] - bestS[dp_i]. ll newKey = 2*S[i] - bestS[dp_i]; int newIdx = int(upper_bound(allS.begin(), allS.end(), newKey) - allS.begin()); // And we want to minimize bestS[dp_i+1] bestS[dp_i+1] = min(bestS[dp_i+1], S[i]); // Finally update Fenwick so future positions can see dp_i+1 dpFenw.update(newIdx, dp_i+1); } cout << answer << "\n"; return 0; }
#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...