Submission #395511

#TimeUsernameProblemLanguageResultExecution timeMemory
395511rama_pangSegments (IZhO18_segments)C++17
100 / 100
1963 ms10604 KiB
#include <bits/stdc++.h>
using namespace std;

const int BLOCK = 1800;
const int BSIZE = 200005 / BLOCK + 5;

class Solver {
 public:
  vector<pair<int, int>> pending;
  vector<pair<int, int>> intervals;

  vector<int> lengths[BSIZE]; // (r - l + 1)
  pair<int, int> minmaxl[BSIZE]; // min and max l in blockslr[]
  vector<pair<int, int>> blockslr[BSIZE]; // (l, r)

  int Isect(int a, int b, int l, int r) {
    return max(0, min(b, r) - max(a, l) + 1);
  }

  void Insert(int l, int r) {
    pending.emplace_back(l, r);
    if (pending.size() >= BLOCK) {
      for (auto p : pending) intervals.emplace_back(p);
      sort(begin(intervals), end(intervals));
      pending.clear();

      for (int i = 0; i < int(intervals.size()); i += BLOCK) {
        int b = i / BLOCK;
        lengths[b].clear();
        blockslr[b].clear();
        minmaxl[b] = {intervals[i].first, intervals[i].first};
        for (int j = i; j < min(int(intervals.size()), i + BLOCK); j++) {
          lengths[b].emplace_back(intervals[j].second - intervals[j].first + 1);
          blockslr[b].emplace_back(intervals[j]);
          minmaxl[b].first  = min(minmaxl[b].first,  intervals[j].first);
          minmaxl[b].second = max(minmaxl[b].second, intervals[j].first);
        }
        sort(begin(lengths[b]), end(lengths[b]));
        sort(begin(blockslr[b]), end(blockslr[b]), [&](auto &x, auto &y) {
          return x.second < y.second;
        });
      }
    }
  }

  int Query(int l, int r, int k) {
    if (r - l + 1 < k) return 0;

    int res = 0;
    for (auto p : pending) res += Isect(p.first, p.second, l, r) >= k;

    for (int i = 0; i < int(intervals.size()); i += BLOCK) {
      int b = i / BLOCK;
      if (minmaxl[b].second < l) {
        // right endpoint must be >= l + k - 1
        int lo = 0, hi = int(blockslr[b].size());
        while (lo < hi) {
          int md = (lo + hi) / 2;
          if (blockslr[b][md].second >= l + k - 1) {
            hi = md;
          } else {
            lo = md + 1;
          }
        }
        res += int(blockslr[b].size()) - lo;
      } else if (minmaxl[b].first < l && l <= minmaxl[b].second) { // will only trigger once
        for (auto p : blockslr[b]) res += Isect(p.first, p.second, l, r) >= k;
      } else if (l <= minmaxl[b].first && minmaxl[b].second <= r - k + 1) {
        // must count interval length >= k
        int lo = 0, hi = int(lengths[b].size());
        while (lo < hi) {
          int md = (lo + hi) / 2;
          if (lengths[b][md] >= k) {
            hi = md;
          } else {
            lo = md + 1;
          }
        }
        res += int(lengths[b].size()) - lo;
      } else if (minmaxl[b].first <= r - k + 1 && r - k + 1 < minmaxl[b].second) { // will only trigger once
        for (auto p : blockslr[b]) res += Isect(p.first, p.second, l, r) >= k;
      } else if (r - k + 1 < minmaxl[b].first) {
        // interval intersect on < k points
      } else {
        assert(false);
      }
    }

    return res;
  }
} positive, negative;

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

  int n, t;
  cin >> n >> t;

  int lastans = 0;
  vector<int> l, r;

  while (n--) {
    int type;
    cin >> type;
    if (type == 1) {
      int a, b;
      cin >> a >> b;
      a = (a ^ (t * lastans));
      b = (b ^ (t * lastans));
      if (a > b) swap(a, b);
      l.emplace_back(a);
      r.emplace_back(b);
      positive.Insert(a, b);
    } else if (type == 2) {
      int id;
      cin >> id;
      id--;
      negative.Insert(l[id], r[id]);
    } else if (type == 3) {
      int a, b, k;
      cin >> a >> b >> k;
      a = (a ^ (t * lastans));
      b = (b ^ (t * lastans));
      if (a > b) swap(a, b);
      lastans = positive.Query(a, b, k) - negative.Query(a, b, k);
      cout << lastans << '\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...
#Verdict Execution timeMemoryGrader output
Fetching results...