Submission #926168

#TimeUsernameProblemLanguageResultExecution timeMemory
926168myst6Street Lamps (APIO19_street_lamps)C++14
100 / 100
2422 ms79608 KiB
#include <bits/stdc++.h>

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;
    }
  }
};


// count {t1<t2, a1<a2+1, b1>b2-1} for each query
// because of equality, updates must be processed before queries
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;
}
#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...