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);
      |                             ^~~~~~~~~~~~~~~~~~