Submission #1271789

#TimeUsernameProblemLanguageResultExecution timeMemory
1271789pvb.tunglamZIGZAG (INOI20_zigzag)C++20
100 / 100
534 ms71344 KiB
#include <bits/stdc++.h> using namespace std; using ll = long long; struct Node { ll first, last; // p[l], p[r] int len_p; // number of p elements in segment int d_len; // number of d elements = len_p - 1 ll sum; // total contribution from d runs: sum over runs t*(t+1)/2 int pref; // length of alternating prefix in d (count of d elements) int suff; // length of alternating suffix in d int first_sign; // sign of first d element (0 if none) int last_sign; // sign of last d element (0 if none) Node() { first = last = 0; len_p = d_len = 0; sum = 0; pref = suff = 0; first_sign = last_sign = 0; } }; inline int sgnll(ll x){ if(x>0) return 1; if(x<0) return -1; return 0; } inline ll run_contrib(int t){ return 1LL * t * (t + 1) / 2; } const int MAXN = 300005; vector<Node> seg; vector<ll> lazyAdd; vector<char> lazyFlip; int n,q; vector<ll> a; Node make_leaf(ll val){ Node nd; nd.first = nd.last = val; nd.len_p = 1; nd.d_len = 0; nd.sum = 0; nd.pref = nd.suff = 0; nd.first_sign = nd.last_sign = 0; return nd; } Node mergeNode(const Node &A, const Node &B){ if(A.len_p == 0) return B; if(B.len_p == 0) return A; Node R; R.len_p = A.len_p + B.len_p; R.first = A.first; R.last = B.last; R.d_len = A.d_len + B.d_len + 1; ll total = A.sum + B.sum; int s = sgnll(B.first - A.last); int left_ext = 0; if(A.d_len > 0 && A.suff > 0 && A.last_sign != 0 && s != 0 && A.last_sign * s == -1){ left_ext = A.suff; } int right_ext = 0; if(B.d_len > 0 && B.pref > 0 && B.first_sign != 0 && s != 0 && s * B.first_sign == -1){ right_ext = B.pref; } if(s != 0){ int combined = left_ext + 1 + right_ext; if(left_ext > 0) total -= run_contrib(left_ext); if(right_ext > 0) total -= run_contrib(right_ext); total += run_contrib(combined); } R.sum = total; if(A.d_len > 0) R.first_sign = A.first_sign; else { if(s != 0) R.first_sign = s; else R.first_sign = B.first_sign; } if(B.d_len > 0) R.last_sign = B.last_sign; else { if(s != 0) R.last_sign = s; else R.last_sign = A.last_sign; } // pref if(A.d_len == 0){ if(s == 0){ R.pref = B.pref; } else { int ext = 0; if(B.d_len > 0 && B.pref > 0 && R.first_sign != 0 && R.first_sign * B.first_sign == -1) ext = B.pref; R.pref = 1 + ext; } } else { if(A.pref == A.d_len && s != 0 && A.last_sign * s == -1){ int ext = 0; if(B.d_len > 0 && B.pref > 0 && s * B.first_sign == -1) ext = B.pref; R.pref = A.d_len + 1 + ext; } else R.pref = A.pref; } // suff (fixed logic) if(B.d_len == 0){ if(s == 0){ R.suff = 0; } else { int ext = 0; if(A.d_len > 0 && A.suff > 0 && A.last_sign * s == -1) ext = A.suff; R.suff = 1 + ext; } } else { if(B.suff == B.d_len && s != 0 && s * B.first_sign == -1){ int ext = 0; if(A.d_len > 0 && A.suff > 0 && A.last_sign * s == -1) ext = A.suff; R.suff = B.d_len + 1 + ext; } else R.suff = B.suff; } return R; } void applyAdd(int id, ll v){ lazyAdd[id] += v; seg[id].first += v; seg[id].last += v; // signs and sum/pref/suff unchanged } void applyFlip(int id){ lazyFlip[id] ^= 1; // composition: flip negates pending add lazyAdd[id] = -lazyAdd[id]; seg[id].first = -seg[id].first; seg[id].last = -seg[id].last; // internal d signs are multiplied by -1 => first_sign/last_sign flip sign seg[id].first_sign = -seg[id].first_sign; seg[id].last_sign = -seg[id].last_sign; // sum/pref/suff unchanged (alternation preserved) } void pushDown(int id){ int lc = id<<1, rc = lc|1; if(lc >= (int)seg.size()) return; if(lazyFlip[id]){ applyFlip(lc); applyFlip(rc); lazyFlip[id] = 0; } if(lazyAdd[id] != 0){ applyAdd(lc, lazyAdd[id]); applyAdd(rc, lazyAdd[id]); lazyAdd[id] = 0; } } void build(int id, int l, int r){ lazyAdd[id] = 0; lazyFlip[id] = 0; if(l==r){ seg[id] = make_leaf(a[l]); return; } int mid=(l+r)/2; build(id*2,l,mid); build(id*2+1,mid+1,r); seg[id] = mergeNode(seg[id*2], seg[id*2+1]); } void updateAdd(int id, int l, int r, int ql, int qr, ll v){ if(qr<l || r<ql) return; if(ql<=l && r<=qr){ applyAdd(id, v); return; } pushDown(id); int mid=(l+r)/2; updateAdd(id*2,l,mid,ql,qr,v); updateAdd(id*2+1,mid+1,r,ql,qr,v); seg[id] = mergeNode(seg[id*2], seg[id*2+1]); } void updateFlip(int id, int l, int r, int ql, int qr){ if(qr<l || r<ql) return; if(ql<=l && r<=qr){ applyFlip(id); return; } pushDown(id); int mid=(l+r)/2; updateFlip(id*2,l,mid,ql,qr); updateFlip(id*2+1,mid+1,r,ql,qr); seg[id] = mergeNode(seg[id*2], seg[id*2+1]); } Node queryNode(int id, int l, int r, int ql, int qr){ if(qr<l || r<ql) return Node(); if(ql<=l && r<=qr) return seg[id]; pushDown(id); int mid=(l+r)/2; Node L = queryNode(id*2,l,mid,ql,qr); Node R = queryNode(id*2+1,mid+1,r,ql,qr); return mergeNode(L,R); } inline long long answer_from_node(const Node &nd){ return (long long)nd.len_p + nd.sum; } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); if(!(cin>>n>>q)) return 0; a.assign(n+1,0); for(int i=1;i<=n;i++) cin>>a[i]; seg.assign(4*(n+5), Node()); lazyAdd.assign(4*(n+5), 0); lazyFlip.assign(4*(n+5), 0); build(1,1,n); while(q--){ char t; cin>>t; if(t=='*'){ int l,r; cin>>l>>r; updateFlip(1,1,n,l,r); } else if(t=='+'){ int l,r; ll v; cin>>l>>r>>v; updateAdd(1,1,n,l,r,v); } else if(t=='?'){ int l,r; cin>>l>>r; Node nd = queryNode(1,1,n,l,r); cout << answer_from_node(nd) << '\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...