Submission #789064

#TimeUsernameProblemLanguageResultExecution timeMemory
789064tvladm2009Street Lamps (APIO19_street_lamps)C++17
20 / 100
62 ms6496 KiB
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = (int) 3e5 + 7;
int sol[107][107];
int n, q;
string s;

struct Operation {
  bool type;
  int a;
  int b;
};

vector<Operation> op;

int subtask() {
  if (n <= 100 && q <= 100) {
    return 1;
  }
  for (auto &it : op) {
    if (it.type == 1 && it.b - it.a != 1) {
      return 3;
    }
  }
  return 2;
}

int nodes = 0;

struct Dsu {
  struct History {
    int u;
    int v;
    int oldv;
    int oldszv;
  };

  vector<int> t, sz, par;
  vector<History> st;

  void init(int n) {
    t.resize(n + 1);
    sz.resize(n + 1);
    for (int i = 1; i <= n; i++) {
      t[i] = i;
      sz[i] = 1;
    }
  }

  int root(int u) {
    assert(u <= 6);
    if (t[u] == u) {
      return u;
    }
    return root(t[u]);
  }

  void unite(int u, int v) {
    u = root(u);
    v = root(v);
    if (u != v) {
      if (sz[u] < sz[v]) {
        swap(u, v);
      }
      st.push_back({u, v, t[v], sz[v]});
      t[v] = u;
      sz[u] += sz[v];
    }
  }

  void undo() {
    History aux = st.back();
    st.pop_back();
    t[aux.v] = aux.oldv;
    sz[aux.v] = aux.oldszv;
    sz[aux.u] -= aux.oldszv;
  }
};

struct DynamicConectivity {
  vector<vector<pair<int, int>>> segt;
  Dsu dsu;

  void init(int q, int n) {
    segt.resize(4 * q + 1);
    dsu.init(n);
  }

  void update(int v, int tl, int tr, int x, int y, pair<int, int> edg) {
    if (tr < x || y < tl) {
      return;
    }
    if (x <= tl && tr <= y) {
      segt[v].push_back(edg);
      return;
    }
    int tm = (tl + tr) / 2;
    update(2 * v, tl, tm, x, y, edg);
    update(2 * v + 1, tm + 1, tr, x, y, edg);
  }

  void ins(int x, int y, pair<int, int> edg) {
    update(1, 1, q, x, y, edg);
  }

  vector<pair<int, int>> edges;

  void query(int v, int tl, int tr, int x, int y, int node, int &comp) {
    if (tr < x || y < tl) {
      return;
    }
    int undo = 0;
    /// cout << "! " << v << "\n";
    for (auto &edg : segt[v]) {
      /// cout << edg.first << " " << edg.second << "\n";
      if (dsu.root(edg.first) != dsu.root(edg.second)) {
        undo++;
        assert(edg.first <= 6 && edg.second <= 6);
        dsu.unite(edg.first, edg.second);
      }
    }
    if (x <= tl && tr <= y) {
      comp = dsu.root(node);
      /// for (auto &it : edges) {
        /// cout << it.first << " " << it.second << "\n";
      /// }
      /// cout << "\n";
    } else {
      int tm = (tl + tr) / 2;
      query(2 * v, tl, tm, x, y, node, comp);
      query(2 * v + 1, tm + 1, tr, x, y, node, comp);
    }
    while (undo--) {
      dsu.undo();
      edges.pop_back();
    }
  }

  void del(int n) {
    dsu.init(n);
  }
};

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

  // freopen("input", "r", stdin);

  cin >> n >> q >> s;
  s = "#" + s;
  for (int iq = 1; iq <= q; iq++) {
    string t;
    cin >> t;
    if (t == "toggle") {
      int a;
      cin >> a;
      op.push_back({0, a, -1});
    } else {
      int a, b;
      cin >> a >> b;
      op.push_back({1, a, b});
    }
  }
  if (subtask() == 1) {
    for (int i = 1; i <= n; i++) {
      if (s[i] == '1') {
        int j = i;
        while (j <= n && s[j] == '1') {
          sol[i][j + 1]++;
          j++;
        }
      }
    }
    for (auto &it : op) {
      if (it.type == 1) {
        cout << sol[it.a][it.b] << "\n";
      } else {
        int pos = it.a;
        s[pos] ^= '0' ^ '1';
      }

      for (int i = 1; i <= n; i++) {
        if (s[i] == '1') {
          int j = i;
          while (j <= n && s[j] == '1') {
            sol[i][j + 1]++;
            j++;
          }
        }
      }
    }
    return 0;
  }
  if (subtask() == 2) {
    vector<vector<pair<int, int>>> active(n + 1);
    for (int i = 1; i <= n; i++) {
      if (s[i] == '1') {
        active[i].push_back({0, -1});
      }
    }
    for (int i = 0; i < q; i++) {
      if (op[i].type == 0) {
        int pos = op[i].a;
        if (s[pos] == '0') {
          s[pos] = '1';
          active[pos].push_back({i + 1, -1});
        } else {
          s[pos] = '0';
          active[pos].back().second = i;
        }
      }
    }
    vector<vector<int>> sp(n + 1);
    for (int i = 1; i <= n; i++) {
      if (s[i] == '1') {
        active[i].back().second = q;
      }
      if ((int) active[i].size() == 0) {
        continue;
      }
      sp[i].resize((int) active[i].size());
      sp[i][0] = active[i][0].second - active[i][0].first + 1;
      for (int j = 1; j < (int) active[i].size(); j++) {
        sp[i][j] = sp[i][j - 1] + active[i][j].second - active[i][j].first + 1;
      }
    }
    function<int(int, int)> get = [&](int pos, int t) {
      int low = 0, high = (int) active[pos].size() - 1, x = -1;
      while (low <= high) {
        int mid = (low + high) / 2;
        if (active[pos][mid].second <= t) {
          low = mid + 1;
          x = mid;
        } else {
          high = mid - 1;
        }
      }
      int sol = 0;
      if (x != -1) {
        sp[pos][x];
      }
      if (x + 1 < (int) active[pos].size() && active[pos][x + 1].first <= t) {
        sol += t - active[pos][x + 1].first + 1;
      }
      return sol;
    };
    for (int i = 0; i < q; i++) {
      if (op[i].type == 1) {
        assert(op[i].a + 1 == op[i].b);
        cout << get(op[i].a, i) << "\n";
      }
    }
    return 0;
  }
  if (subtask() == 3) {
    DynamicConectivity dc;
    dc.init(q + 1, n + 1);
    for (int i = 1; i <= n; i++) {
      if (s[i] == '1') {
        dc.ins(1, q + 1, {i, i + 1});
      }
    }

    for (int i = 0; i < q; i++) {
      if (op[i].type == 0) {
        dc.ins(i + 2, q + 1, {op[i].a, op[i].a + 1});
      }
    }

    /// int comp = 0;
    /// dc.query(1, 1, q + 1, 1, 6, 4, comp);
    ///cout << comp << "\n";
    /// return 0;

    for (int i = 0; i < q; i++) {
      if (op[i].type == 1) {
        int a = op[i].a;
        int b = op[i].b;
        int low = 1, high = i + 2, sol = -1;
        while (low <= high) {
          int mid = (low + high) / 2;
          int compa = 0, compb = 0;
          dc.query(1, 1, q + 1, 1, mid, a, compa);
          dc.query(1, 1, q + 1, 1, mid, b, compb);
          /// cout << mid << " " << a << " " << b << " => " << compa << " " << compb << "\n";
          if (compa == compb) {
            sol = mid;
            high = mid - 1;
          } else {
            low = mid + 1;
          }
        }
        if (sol == -1) {
          cout << "0\n";
        } else {
          cout << i + 2 - sol << "\n";
          /// cout << i << " " << sol << "\n";
        }
      }
    }
    return 0;
  }
  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...