Submission #1181866

#TimeUsernameProblemLanguageResultExecution timeMemory
1181866mehmetkaganProgression (NOI20_progression)C++20
57 / 100
606 ms51324 KiB
#include <bits/stdc++.h> using namespace std; typedef long long ll; struct Node { ll leftVal, rightVal; int prefLen, suffLen, maxLen; bool allSame; }; const int NMAX = 300000; ll A[NMAX+1]; // difficulties (1-indexed) ll D[NMAX]; // differences: D[i] = A[i+1]-A[i] for i=1..N-1 // Segment tree arrays Node seg[4*NMAX]; ll lazyAdd[4*NMAX]; // for additive updates on differences ll lazySet[4*NMAX]; // for assignment updates on differences (use some flag to indicate assignment pending) bool pendingSet[4*NMAX]; Node combine(const Node &L, const Node &R) { if(L.maxLen == 0) return R; if(R.maxLen == 0) return L; Node res; res.leftVal = L.leftVal; res.rightVal = R.rightVal; // Initially set prefix and suffix lengths: res.prefLen = L.prefLen; res.suffLen = R.suffLen; res.maxLen = max(L.maxLen, R.maxLen); res.allSame = (L.allSame && R.allSame && (L.rightVal == R.leftVal)); // Try to merge L.suff and R.pref if boundary matches. if(L.rightVal == R.leftVal) { int merged = L.suffLen + R.prefLen; res.maxLen = max(res.maxLen, merged); if(L.allSame) res.prefLen = L.prefLen + R.prefLen; if(R.allSame) res.suffLen = R.suffLen + L.suffLen; } return res; } void build(int idx, int l, int r) { if(l == r) { seg[idx].leftVal = D[l]; seg[idx].rightVal = D[l]; seg[idx].prefLen = seg[idx].suffLen = seg[idx].maxLen = 1; seg[idx].allSame = true; return; } int mid = (l+r)/2; build(idx*2, l, mid); build(idx*2+1, mid+1, r); seg[idx] = combine(seg[idx*2], seg[idx*2+1]); } // Utility: apply assignment update on seg[node] for interval [l, r] void applySet(int idx, int l, int r, ll val) { seg[idx].leftVal = seg[idx].rightVal = val; seg[idx].prefLen = seg[idx].suffLen = seg[idx].maxLen = (r-l+1); seg[idx].allSame = true; lazySet[idx] = val; pendingSet[idx] = true; lazyAdd[idx] = 0; // clear additive lazy } // Utility: apply additive update on seg[node] for interval [l, r] void applyAdd(int idx, int l, int r, ll addVal) { seg[idx].leftVal += addVal; seg[idx].rightVal += addVal; if(pendingSet[idx]) { lazySet[idx] += addVal; } else { lazyAdd[idx] += addVal; } } void pushDown(int idx, int l, int r) { int mid = (l+r)/2; int leftChild = idx*2, rightChild = idx*2+1; if(pendingSet[idx]) { applySet(leftChild, l, mid, lazySet[idx]); applySet(rightChild, mid+1, r, lazySet[idx]); pendingSet[idx] = false; lazySet[idx] = 0; } if(lazyAdd[idx] != 0) { applyAdd(leftChild, l, mid, lazyAdd[idx]); applyAdd(rightChild, mid+1, r, lazyAdd[idx]); lazyAdd[idx] = 0; } } void updateRangeSet(int idx, int l, int r, int ql, int qr, ll val) { if(ql > r || qr < l) return; if(ql <= l && r <= qr) { applySet(idx, l, r, val); return; } pushDown(idx, l, r); int mid = (l+r)/2; updateRangeSet(idx*2, l, mid, ql, qr, val); updateRangeSet(idx*2+1, mid+1, r, ql, qr, val); seg[idx] = combine(seg[idx*2], seg[idx*2+1]); } void updateRangeAdd(int idx, int l, int r, int ql, int qr, ll addVal) { if(ql > r || qr < l) return; if(ql <= l && r <= qr) { applyAdd(idx, l, r, addVal); return; } pushDown(idx, l, r); int mid = (l+r)/2; updateRangeAdd(idx*2, l, mid, ql, qr, addVal); updateRangeAdd(idx*2+1, mid+1, r, ql, qr, addVal); seg[idx] = combine(seg[idx*2], seg[idx*2+1]); } Node queryRange(int idx, int l, int r, int ql, int qr) { if(ql > r || qr < l) return Node{0,0,0,0,0,true}; // identity; be careful when merging if(ql <= l && r <= qr) return seg[idx]; pushDown(idx, l, r); int mid = (l+r)/2; Node leftRes = queryRange(idx*2, l, mid, ql, qr); Node rightRes = queryRange(idx*2+1, mid+1, r, ql, qr); if(leftRes.maxLen == 0) return rightRes; if(rightRes.maxLen == 0) return leftRes; return combine(leftRes, rightRes); } // // Main – processing operations and queries. // // NOTE: In an actual contest solution, you would use fast I/O routines. // Also, you need to maintain a separate data structure for A so that you can answer point queries (for the boundaries of the difference array) quickly, // especially when processing rewrite operations. For brevity, these parts are omitted here, but the idea is similar: you can use a lazy segment tree for A as well. // int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int N, Q; cin >> N >> Q; for (int i = 1; i <= N; i++) { cin >> A[i]; } // Build the difference array for (int i = 1; i < N; i++) { D[i] = A[i+1] - A[i]; } if(N > 1) build(1, 1, N-1); while(Q--){ int t; cin >> t; if(t == 1){ int L, R; ll S, C; cin >> L >> R >> S >> C; // Update A on [L,R] with add operation: // (Implementation for updating A is omitted for brevity.) // Update differences: if(L > 1){ // D[L-1] increases by S. updateRangeAdd(1, 1, N-1, L-1, L-1, S); } if(R < N){ // D[R] decreases by S + (R-L)*C. updateRangeAdd(1, 1, N-1, R, R, -(S + (ll)(R - L)*C)); } if(L <= R-1){ // All differences in [L, R-1] add C. updateRangeAdd(1, 1, N-1, L, R-1, C); } } else if(t == 2){ int L, R; ll S, C; cin >> L >> R >> S >> C; // Rewrite A on [L,R]: // (Again, update the A array with an assignment lazy tree; omitted here.) if(L > 1){ // New D[L-1] = new A[L] - A[L-1] = S - A[L-1]. // Retrieve A[L-1] (using your A structure) and then update. ll newVal = S; // new A[L] // For example, assume we can get A[L-1] in O(logN) time. // Here we just use a placeholder. ll prevA = A[L-1]; updateRangeSet(1, 1, N-1, L-1, L-1, S - prevA); } if(R < N){ // New D[R] = A[R+1] - new A[R] = A[R+1] - (S + (R-L)*C). ll nextA = A[R+1]; // get from A structure updateRangeSet(1, 1, N-1, R, R, nextA - (S + (ll)(R-L)*C)); } if(L <= R-1){ // Set differences in [L, R-1] to constant C. updateRangeSet(1, 1, N-1, L, R-1, C); } } else if(t == 3){ int L, R; cin >> L >> R; if(L == R) { cout << 1 << "\n"; } else { // Query differences in [L, R-1] Node ans = queryRange(1, 1, N-1, L, R-1); // Answer is max constant differences length + 1. cout << ans.maxLen + 1 << "\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...
#Verdict Execution timeMemoryGrader output
Fetching results...