Submission #189134

#TimeUsernameProblemLanguageResultExecution timeMemory
189134AlexPop28Street Lamps (APIO19_street_lamps)C++11
100 / 100
2992 ms172412 KiB
#include <bits/stdc++.h>
#define dbg() cerr <<
#define name(x) (#x) << ": " << (x) << ' ' <<

using namespace std;

struct Fenwick {
  int n;
  vector<int> tree;
  Fenwick(int n_ = 0) : n(n_), tree(n + 1) {}
  inline int lsb(int x) {
    return x & -x;
  }
  void Update(int pos, int val) {
    for (++pos; pos <= n; pos += lsb(pos))
      tree[pos] += val;
  }
  void Update(int left, int right, int val) {
    Update(left, val);
    Update(right + 1, -val);
  }
  int Query(int pos) {
    int ans = 0;
    for (++pos; pos; pos -= lsb(pos))
      ans += tree[pos];
    return ans;
  }
};

struct SegmTree {
  int n;
  vector<Fenwick> tree;
  vector<vector<int>> qrs;
  SegmTree(int n_) : n(n_), tree(4 * n), qrs(4 * n) {}
  void Build() {
    for (int node = 0; node < 4 * n; ++node) {
      sort(qrs[node].begin(), qrs[node].end());
      qrs[node].erase(unique(qrs[node].begin(), qrs[node].end()), qrs[node].end());
      tree[node] = Fenwick(qrs[node].size());
    }
  }

  void AddQuery(int node, int left, int right, int a, int b) {
    qrs[node].emplace_back(b);
    if (left == right) return;
    int mid = left + (right - left) / 2;
    if (a <= mid) {
      AddQuery(2 * node + 1, left, mid, a, b);
    } else {
      AddQuery(2 * node + 2, mid + 1, right, a, b);
    }
  }

  void Update(int node, int left, int right, int x, int y, int val) {
    if (qrs[node].empty()) return;
    if (x <= left && right <= y) {
      // vreau queryurile care au capatul dreapta <= y
      // capatul stanga imi e asigurat de aint
      int pos = upper_bound(qrs[node].begin(), qrs[node].end(), y) -
                qrs[node].begin() - 1;
      tree[node].Update(0, pos, val);
      return; 
    }

    int mid = left + (right - left) / 2;
    if (x <= mid) {
      Update(2 * node + 1, left, mid, x, y, val);
    }
    if (mid < y) {
      Update(2 * node + 2, mid + 1, right, x, y, val);
    }
  }

  int Query(int node, int left, int right, int x, int y) {
    if (qrs[node].empty()) return 0;
    int pos = lower_bound(qrs[node].begin(), qrs[node].end(), y) -
              qrs[node].begin();
    int ans = tree[node].Query(pos);
    if (left == right) return ans;
    
    int mid = left + (right - left) / 2;
    if (x <= mid) {
      ans += Query(2 * node + 1, left, mid, x, y);
    } else {
      ans += Query(2 * node + 2, mid + 1, right, x, y);
    }
    return ans;
  }

  void AddQuery(int a, int b) {
    AddQuery(0, 0, n - 1, a, b);
  }

  void TurnOn(int l, int r, int t) {
    Update(0, 0, n - 1, l, r, -t);
  }

  void TurnOff(int l, int r, int t) {
    Update(0, 0, n - 1, l, r, +t);
  }

  int Query(int l, int r) {
    return Query(0, 0, n - 1, l, r); 
  }
};

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);

  int n, q; cin >> n >> q;
  string s; cin >> s;
  SegmTree st(n);
  vector<tuple<int, int, int>> qrs(q);
  for (auto &e : qrs) {
    string t; cin >> t;
    if (t[0] == 't') {
      int pos; cin >> pos; --pos;
      e = make_tuple(0, pos, -1);
    } else {
      int a, b; cin >> a >> b; --a, --b, --b;
      e = make_tuple(1, a, b);
      st.AddQuery(a, b);
    }
  }
  st.Build();

  set<pair<int, int>> ones;
  for (int i = 0; i < n; ) {
    if (s[i] == '0') {
      ++i;
    } else {
      int j = i;
      while (i < n && s[i] == '1') ++i;
      ones.emplace(j, i - 1);
    }
  }
   
  for (int t = 1; t <= q; ++t) {
    int type, x, y; tie(type, x, y) = qrs[t - 1];
    if (type == 0) {
      if (s[x] == '0') {
        int l = x, r = x;
        auto it = ones.lower_bound({x, 0});

        if (it != ones.begin()) {
          if (prev(it)->second == x - 1) {
            l = prev(it)->first;
            it = ones.erase(prev(it));
            st.TurnOff(l, x - 1, t);
          }
        }

        if (it != ones.end()) {
          if (it->first == x + 1) {
            r = it->second;
            ones.erase(it);
            st.TurnOff(x + 1, r, t);
          }
        }

        ones.emplace(l, r);
        st.TurnOn(l, r, t);
      } else {
        auto it = ones.upper_bound({x, n}); --it;
        assert(it->first <= x && x <= it->second);
        int l, r; tie(l, r) = *it;

        if (x != l) {
          ones.emplace(l, x - 1);
          st.TurnOn(l, x - 1, t);
        }
        if (x != r) {
          ones.emplace(x + 1, r);
          st.TurnOn(x + 1, r, t);
        }

        ones.erase(it);
        st.TurnOff(l, r, t);
      }
      s[x] ^= '0' ^ '1';
    } else {
      int ans = st.Query(x, y);
      auto it = ones.upper_bound({x, n});
      if (it != ones.begin()) {
        --it;
        assert(it->first <= x);
        if (it->second >= y) {
          ans += t;
        }
      }
      cout << ans << '\n';
    }
  }
}
#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...