Submission #1326556

#TimeUsernameProblemLanguageResultExecution timeMemory
1326556ee23b179_cpStreet Lamps (APIO19_street_lamps)C++20
Compilation error
0 ms0 KiB
#include <bits/stdc++.h> /* - Maintain a set of maximal segments of contiguous ones. - Whenever a segment is removed, create a point (a, b, -t). - Whenever a segment is added, create a point (a, b, +t). - Now for each query (aq, bq, tq), count the number of points (a, b, t) such that a < aq , b > bq , t < tq - Find the total sum of t, and the number of negative and positive events. - If one positive event is missing, add 't' into the total sum. - This can be easily solved with CDQ divide and conquer. - My previous idea was using a 2D sparse segment tree to do the same, but it uses too much memory. Alas, the remnants of my code were still there, so i decided to reuse the 1D version instead of creating a new code for a regular segment tree. */ using namespace std; using ll = long long; struct Node; const int s1 = 2'000'000; vector<Node> node(s1); int next1 = 1; int n; struct Node { int left, right; pair<ll,int> val; Node() : left(0), right(0), val({0,0}) {} void update(int v, int xl, int xr, int add, int ct) { if (v < xl || v > xr) return; val.first += add; val.second += ct; if (xl != xr) { int xm = (xl + xr) / 2; if (v <= xm) { if (!left) left = next1++; node[left].update(v, xl, xm, add, ct); } else { if (!right) right = next1++; node[right].update(v, xm+1, xr, add, ct); } } } pair<ll,int> query(int l, int r, int xl, int xr) { if (l > r) return {0, 0}; if (l == xl && r == xr) { return val; } else { pair<ll,int> ans = {0, 0}; int xm = (xl + xr) / 2; if (left) { pair<ll,int> leftans = node[left].query(l, min(r, xm), xl, xm); ans.first += leftans.first; ans.second += leftans.second; } if (right) { pair<ll,int> rightans = node[right].query(max(l, xm+1), r, xm+1, xr); ans.first += rightans.first; ans.second += rightans.second; } return ans; } } }; Node onTree, offTree; vector<array<int,5>> updates; vector<ll> offSum, onSum; vector<int> offCount, onCount; void cdq(int l, int r) { if (l == r) return; int m = (l + r) / 2; cdq(l, m); cdq(m+1, r); sort(updates.begin() + l, updates.begin() + m + 1, [&](array<int,5> A, array<int,5> B) -> bool { return A[1] < B[1]; }); sort(updates.begin() + m + 1, updates.begin() + r + 1, [&](array<int,5> A, array<int,5> B) -> bool { return A[1] < B[1]; }); stack<pair<int,int>> offActions, onActions; int a = l, b = m+1; while (a <= m || b <= r) { bool isleft; int cur; if (a > m || (b <= r && updates[b][1] <= updates[a][1])) cur = b++, isleft = 0; else cur = a++, isleft = 1; if (updates[cur][3] == -1 && isleft) { offTree.update(updates[cur][2], 0, n-1, updates[cur][0], +1); offActions.push({updates[cur][2], updates[cur][0]}); } else if (updates[cur][3] == 1 && isleft) { onTree.update(updates[cur][2], 0, n-1, updates[cur][0], +1); onActions.push({updates[cur][2], updates[cur][0]}); } else if (updates[cur][3] == 0 && !isleft) { int qi = updates[cur][4]; pair<ll,int> onDat = onTree.query(updates[cur][2]+1, n-1, 0, n-1); onSum[qi] += onDat.first; onCount[qi] += onDat.second; pair<ll,int> offDat = offTree.query(updates[cur][2]+1, n-1, 0, n-1); offSum[qi] += offDat.first; offCount[qi] += offDat.second; } } while (offActions.size()) { offTree.update(offActions.top().first, 0, n-1, -offActions.top().second, -1); offActions.pop(); } while (onActions.size()) { onTree.update(onActions.top().first, 0, n-1, -onActions.top().second, -1); onActions.pop(); } } int main() { int q; cin >> n >> q; string s; cin >> s; set<array<int,2>> segments; for (int i=0; i<n; i++) { if (s[i] == '1') { int l = i; while (i < n-1 && s[i+1] == '1') i++; segments.insert({l, i}); updates.push_back({0, l, i, +1}); } } int qc = 0; vector<int> qtime; for (int t=1; t<=q; t++) { string type; cin >> type; if (type == "toggle") { int i; cin >> i; i--; if (s[i] == '0') { int l = i, r = i; auto right = segments.lower_bound({i, i}); if (right != segments.end() && right->at(0) == i+1) { r = right->at(1); updates.push_back({t, i+1, r, -1}); segments.erase(right); } auto left = segments.lower_bound({i, i}); if (left != segments.begin()) --left; if (left != segments.end() && left->at(1) == i-1) { l = left->at(0); updates.push_back({t, l, i-1, -1}); segments.erase(left); } segments.insert({l, r}); updates.push_back({t, l, r, +1}); s[i] = '1'; } else { auto it = prev(segments.lower_bound({i+1, i+1})); int l = it->at(0), r = it->at(1); segments.erase(it); updates.push_back({t, l, r, -1}); if (l < i) { segments.insert({l, i-1}); updates.push_back({t, l, i-1, +1}); } if (r > i) { segments.insert({i+1, r}); updates.push_back({t, i+1, r, +1}); } s[i] = '0'; } } else { int a, b; cin >> a >> b; updates.push_back({t, a, b-3, 0, qc++}); qtime.push_back(t); } } sort(updates.begin(), updates.end()); offSum.resize(qc); onSum.resize(qc); offCount.resize(qc); onCount.resize(qc); cdq(0, (int) updates.size() - 1); for (int i=0; i<qc; i++) { ll ans = offSum[i] - onSum[i]; if (onCount[i] > offCount[i]) ans += qtime[i]; cout << ans << "\n"; } return 0; }

Compilation message (stderr)

In file included from /usr/include/c++/13/vector:66,
                 from /usr/include/c++/13/functional:64,
                 from /usr/include/x86_64-linux-gnu/c++/13/bits/stdc++.h:53,
                 from street_lamps.cpp:1:
/usr/include/c++/13/bits/stl_vector.h: In instantiation of 'static constexpr std::vector<_Tp, _Alloc>::size_type std::vector<_Tp, _Alloc>::_S_max_size(const _Tp_alloc_type&) [with _Tp = Node; _Alloc = std::allocator<Node>; size_type = long unsigned int; _Tp_alloc_type = std::vector<Node>::_Tp_alloc_type]':
/usr/include/c++/13/bits/stl_vector.h:1909:23:   required from here
street_lamps.cpp:25:21:   in 'constexpr' expansion of 'node.std::vector<Node>::vector(((std::vector<Node>::size_type)((int)s1)), std::allocator<Node>())'
/usr/include/c++/13/bits/stl_vector.h:557:32:   in 'constexpr' expansion of 'std::vector<Node>::_S_check_init_len(__n, (* & __a))'
/usr/include/c++/13/bits/stl_vector.h:1922:61: error: invalid application of 'sizeof' to incomplete type 'Node'
 1922 |           = __gnu_cxx::__numeric_traits<ptrdiff_t>::__max / sizeof(_Tp);
      |                                                             ^~~~~~~~~~~
In file included from /usr/include/c++/13/ext/alloc_traits.h:34,
                 from /usr/include/c++/13/bits/basic_string.h:39,
                 from /usr/include/c++/13/string:54,
                 from /usr/include/c++/13/bitset:52,
                 from /usr/include/x86_64-linux-gnu/c++/13/bits/stdc++.h:52:
/usr/include/c++/13/bits/alloc_traits.h: In instantiation of 'static constexpr std::allocator_traits<std::allocator<_CharT> >::size_type std::allocator_traits<std::allocator<_CharT> >::max_size(const allocator_type&) [with _Tp = Node; size_type = long unsigned int; allocator_type = std::allocator<Node>]':
/usr/include/c++/13/bits/stl_vector.h:1923:51:   required from 'static constexpr std::vector<_Tp, _Alloc>::size_type std::vector<_Tp, _Alloc>::_S_max_size(const _Tp_alloc_type&) [with _Tp = Node; _Alloc = std::allocator<Node>; size_type = long unsigned int; _Tp_alloc_type = std::vector<Node>::_Tp_alloc_type]'
/usr/include/c++/13/bits/stl_vector.h:1909:23:   required from here
/usr/include/c++/13/bits/alloc_traits.h:576:29: error: invalid application of 'sizeof' to incomplete type 'std::allocator_traits<std::allocator<Node> >::value_type' {aka 'Node'}
  576 |         return size_t(-1) / sizeof(value_type);
      |                             ^~~~~~~~~~~~~~~~~~