Problem p00525 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>
using namespace std;
typedef long long lint;
typedef pair<int, int> pi;

struct seg {
  int s, e, x;
  bool operator<(const seg &s) const { return x < s.x; }
};

struct sweep {
  int idx, pos, val;
  bool operator<(const sweep &s) const {
    return pi(idx, val) < pi(s.idx, s.val);
  }
};

struct disj {
  int pa[100050];
  void init(int n) {
    for (int i = 1; i <= n; i++)
      pa[i] = i;
  }
  int find(int x) { return pa[x] = (pa[x] == x ? x : find(pa[x])); }
  bool uni(int p, int q) {
    p = find(p);
    q = find(q);
    if (p == q)
      return 0;
    pa[q] = p;
    return 1;
  }
} disj;

int xsz, ysz;
vector<seg> xs, ys;

int ds[200050];

const int B = 400;
int bkt[505][405];
int rep[505];

void bkt_push(int x) {
  if (rep[x] == 0)
    return;
  for (int i = 0; i < B; i++) {
    if (bkt[x][i]) {
      bkt[x][i] = rep[x];
    }
  }
  rep[x] = 0;
}

void bkt_insert(int p, int v) {
  bkt_push(p / B);
  bkt[p / B][p % B] = v;
}

void bkt_merge(int s, int e, int x) {
  if (s / B == e / B) {
    bkt_push(s / B);
    for (int i = s % B; i <= e % B; i++) {
      if (bkt[s / B][i]) {
        disj.uni(bkt[s / B][i], x);
      }
    }
    return;
  }
  if (s % B)
    bkt_push(s / B);
  while (s % B) {
    if (bkt[s / B][s % B]) {
      disj.uni(bkt[s / B][s % B], x);
    }
    s++;
  }
  if (e % B != B - 1)
    bkt_push(e / B);
  while (e % B != B - 1) {
    if (bkt[e / B][e % B]) {
      disj.uni(bkt[e / B][e % B], x);
    }
    e--;
  }
  for (int i = s / B; i <= e / B; i++) {
    if (rep[i]) {
      disj.uni(rep[i], x);
    } else {
      int chk = 0;
      for (int j = 0; j < B; j++) {
        if (bkt[i][j]) {
          disj.uni(bkt[i][j], x);
          chk++;
        }
      }
      if (chk)
        rep[i] = x;
    }
  }
}

int get_component() {
  disj.init(xs.size());
  vector<sweep> swp;
  set<int> s;
  for (auto &i : xs) {
    swp.push_back({i.s, i.x, 1});
    swp.push_back({i.e + 1, i.x, -1});
  }
  sort(swp.begin(), swp.end());
  int p = 0, q = 0, r = 0;
  int cnt = 1;
  for (int i = 1; i <= ysz + 1; i++) {
    while (p < swp.size() && swp[p].idx == i) {
      if (swp[p].val == 1) {
        ds[swp[p].pos] = ++r;
        bkt_insert(swp[p].pos, r);
        s.insert(swp[p].pos);
      } else {
        bkt_insert(swp[p].pos, 0);
        s.erase(swp[p].pos);
      }
      p++;
    }
    while (q < ys.size() && ys[q].x == i) {
      auto t = s.lower_bound(ys[q].s);
      if (t == s.end() || *t > ys[q].e) {
        cnt++;
        q++;
        continue;
      }
      bkt_merge(ys[q].s, ys[q].e, ds[*t]);
      q++;
    }
  }
  for (int i = 2; i <= xs.size(); i++) {
    if (disj.uni(1, i))
      cnt++;
  }
  return cnt;
}

struct bit {
  int tree[200050];
  void add(int x, int v) {
    while (x <= xsz) {
      tree[x] += v;
      x += x & -x;
    }
  }
  int query(int x) {
    int ret = 0;
    while (x) {
      ret += tree[x];
      x -= x & -x;
    }
    return ret;
  }
} bit;

lint get_intersection() {
  vector<sweep> swp;
  for (auto &i : xs) {
    swp.push_back({i.s, i.x, 1});
    swp.push_back({i.e + 1, i.x, -1});
  }
  sort(swp.begin(), swp.end());
  lint ret = 0;
  int p = 0;
  for (auto &j : ys) {
    while (p < swp.size() && swp[p].idx <= j.x) {
      bit.add(swp[p].pos, swp[p].val);
      p++;
    }
    ret += bit.query(j.e) - bit.query(j.s - 1);
  }
  return ret;
}

int main() {
  vector<int> vx, vy;
  int w, h, n;
  scanf("%d %d %d", &w, &h, &n);
  vx.push_back(0);
  vx.push_back(w);
  vy.push_back(0);
  vy.push_back(h);
  for (int i = 0; i < n; i++) {
    int x1, y1, x2, y2;
    scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
    vx.push_back(x1);
    vx.push_back(x2);
    vy.push_back(y1);
    vy.push_back(y2);
    if (x1 < x2) {
      ys.push_back({x1, x2, y1});
    }
    if (y1 < y2) {
      xs.push_back({y1, y2, x1});
    }
  }
  xs.push_back({0, h, 0});
  xs.push_back({0, h, w});
  ys.push_back({0, w, 0});
  ys.push_back({0, w, h});
  sort(xs.begin(), xs.end());
  sort(ys.begin(), ys.end());
  sort(vx.begin(), vx.end());
  sort(vy.begin(), vy.end());
  vx.resize(unique(vx.begin(), vx.end()) - vx.begin());
  vy.resize(unique(vy.begin(), vy.end()) - vy.begin());
  for (auto &i : xs) {
    int l = lower_bound(vy.begin(), vy.end(), i.s) - vy.begin();
    int r = upper_bound(vy.begin(), vy.end(), i.e) - vy.begin() - 1;
    int x = lower_bound(vx.begin(), vx.end(), i.x) - vx.begin();
    i = {l + 1, r + 1, x + 1};
  }
  for (auto &i : ys) {
    int l = lower_bound(vx.begin(), vx.end(), i.s) - vx.begin();
    int r = upper_bound(vx.begin(), vx.end(), i.e) - vx.begin() - 1;
    int x = lower_bound(vy.begin(), vy.end(), i.x) - vy.begin();
    i = {l + 1, r + 1, x + 1};
  }
  xsz = vx.size();
  ysz = vy.size();
  cout << get_intersection() + get_component() - (n + 4) << endl;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <map>
#include <utility>
#include <vector>
using namespace std;
typedef long long lint;
typedef pair<int, int> pi;

struct line {
  int s, e, x;
};
bool cmp(line a, line b) { return a.x < b.x; }

struct event {
  int px, py, num;
};
bool cmp2(event a, event b) { return a.px < b.px; }

struct disj {
  int pa[100005];
  void init(int n) {
    for (int i = 0; i <= n; i++)
      pa[i] = i;
  }
  int find(int x) { return pa[x] = (pa[x] == x ? x : find(pa[x])); }
  void uni(int p, int q) { pa[find(p)] = find(q); }
} disj;

struct bit {
  int tree[200050], lim;
  void init(int n) {
    lim = n + 2;
    memset(tree, 0, sizeof(tree));
  }
  void add(int x, int v) {
    x += 2;
    while (x <= lim) {
      tree[x] += v;
      x += x & -x;
    }
  }
  int sum(int x) {
    x += 2;
    int ret = 0;
    while (x) {
      ret += tree[x];
      x -= x & -x;
    }
    return ret;
  }
  int range_sum(int s, int e) { return sum(e) - sum(s - 1); }
} bit;

struct seg {
  int tree[270000], eraser[270000];
  void add(int s, int e, int ps, int pe, int p, int v) {
    for (int i = s; i <= e; i++) {
      tree[i] = v;
    }
  }
  void erase(int s, int e, int ps, int pe, int p) {
    for (int i = s; i <= e; i++) {
      tree[i] = -1;
    }
  }
  void fill(int s, int e, int ps, int pe, int p, int v) {
    for (int i = s; i <= e; i++) {
      if (tree[i] != -1)
        disj.uni(tree[i], v);
    }
  }
} seg;

vector<line> linex, liney;
vector<int> vx, vy;
vector<pi> extreme;

vector<pi> sweep_add, sweep_del;

lint vertex() {
  for (auto &i : liney) {
    sweep_add.push_back(pi(i.s + 1, i.x));
    sweep_del.push_back(pi(i.e, i.x));
  }
  sort(sweep_add.begin(), sweep_add.end());
  sort(sweep_del.begin(), sweep_del.end());
  bit.init((int)vy.size());
  int p1 = 0, p2 = 0, p3 = 0;
  lint ret = 0;
  for (int i = 0; i < vx.size(); i++) {
    while (p1 < sweep_add.size() && sweep_add[p1].first == i) {
      bit.add(sweep_add[p1].second, 1);
      p1++;
    }
    while (p2 < sweep_del.size() && sweep_del[p2].first == i) {
      bit.add(sweep_del[p2].second, -1);
      p2++;
    }
    while (p3 < linex.size() && linex[p3].x == i) {
      ret += bit.range_sum(linex[p3].s + 1, linex[p3].e - 1);
      p3++;
    }
  }
  sweep_add.clear();
  sweep_del.clear();
  sort(extreme.begin(), extreme.end());
  extreme.resize(unique(extreme.begin(), extreme.end()) - extreme.begin());
  ret += extreme.size();
  // printf("vertex = %lld\\n",ret);
  return ret;
}

lint edge() {
  lint ret = 0;
  for (auto &i : liney) {
    sweep_add.push_back(pi(i.s, i.x));
    sweep_del.push_back(pi(i.e + 1, i.x));
  }
  sort(sweep_add.begin(), sweep_add.end());
  sort(sweep_del.begin(), sweep_del.end());
  bit.init((int)vy.size());
  int p1 = 0, p2 = 0, p3 = 0;
  for (int i = 0; i < vx.size(); i++) {
    while (p1 < sweep_add.size() && sweep_add[p1].first == i) {
      bit.add(sweep_add[p1].second, 1);
      p1++;
    }
    while (p2 < sweep_del.size() && sweep_del[p2].first == i) {
      bit.add(sweep_del[p2].second, -1);
      p2++;
    }
    while (p3 < linex.size() && linex[p3].x == i) {
      ret += bit.range_sum(linex[p3].s + 1, linex[p3].e - 1) + 1;
      p3++;
    }
  }
  sweep_add.clear();
  sweep_del.clear();
  for (auto &i : linex) {
    sweep_add.push_back(pi(i.s, i.x));
    sweep_del.push_back(pi(i.e + 1, i.x));
  }
  sort(sweep_add.begin(), sweep_add.end());
  sort(sweep_del.begin(), sweep_del.end());
  bit.init((int)vx.size());
  p1 = 0, p2 = 0, p3 = 0;
  for (int i = 0; i < vy.size(); i++) {
    while (p1 < sweep_add.size() && sweep_add[p1].first == i) {
      bit.add(sweep_add[p1].second, 1);
      p1++;
    }
    while (p2 < sweep_del.size() && sweep_del[p2].first == i) {
      bit.add(sweep_del[p2].second, -1);
      p2++;
    }
    while (p3 < liney.size() && liney[p3].x == i) {
      ret += bit.range_sum(liney[p3].s + 1, liney[p3].e - 1) + 1;
      p3++;
    }
  }
  sweep_add.clear();
  sweep_del.clear();
  //   printf("edge = %lld\\n",ret);
  return ret;
}

map<int, int> mp;
vector<event> event_add, event_del;

int component() {
  int pt = 0;
  for (auto &i : liney) {
    event_add.push_back({i.s, i.x, pt});
    event_del.push_back({i.e + 1, i.x, pt});
    pt++;
  }
  sort(event_add.begin(), event_add.end(), cmp2);
  sort(event_del.begin(), event_del.end(), cmp2);
  int p1 = 0, p2 = 0, p3 = 0;
  int ret = 1;
  disj.init((int)liney.size());
  seg.erase(0, (int)vy.size() - 1, 0, (int)vy.size() - 1, 1);
  for (int i = 0; i <= vx.size(); i++) {
    while (p2 < event_del.size() && event_del[p2].px == i) {
      int py = event_del[p2].py;
      seg.erase(py, py, 0, (int)vy.size() - 1, 1);
      mp.erase(mp.find(py));
      p2++;
    }
    while (p1 < event_add.size() && event_add[p1].px == i) {
      int py = event_add[p1].py;

      seg.add(py, py, 0, (int)vy.size() - 1, 1, event_add[p1].num);

      mp[py] = event_add[p1].num;
      p1++;
    }
    while (p3 < linex.size() && linex[p3].x == i) {
      auto t = mp.lower_bound(linex[p3].s);
      if (t == mp.end() || t->first > linex[p3].e) {
        ret++;
        p3++;
        continue;
      }
      seg.fill(linex[p3].s, linex[p3].e, 0, (int)vy.size() - 1, 1, t->second);
      p3++;
    }
  }
  for (int i = 1; i < liney.size(); i++) {
    if (disj.find(0) != disj.find(i)) {
      disj.uni(0, i);
      ret++;
    }
  }
  //  printf("component = %d\\n",ret);
  return ret;
}

int main() {
  int w, h, n;
  scanf("%d %d %d", &w, &h, &n);
  linex.push_back({0, h, 0});
  linex.push_back({0, h, w});
  liney.push_back({0, w, 0});
  liney.push_back({0, w, h});
  vx.push_back(0);
  vy.push_back(0);
  vx.push_back(w);
  vy.push_back(h);
  extreme.push_back(pi(0, 0));
  extreme.push_back(pi(0, h));
  extreme.push_back(pi(w, 0));
  extreme.push_back(pi(w, h));
  for (int i = 0; i < n; i++) {
    int a, b, c, d;
    scanf("%d %d %d %d", &a, &b, &c, &d);
    vx.push_back(a);
    vx.push_back(c);
    vy.push_back(b);
    vy.push_back(d);
    extreme.push_back(pi(a, b));
    extreme.push_back(pi(a, d));
    extreme.push_back(pi(c, b));
    extreme.push_back(pi(c, d));
    if (a == c) {
      linex.push_back({b, d, a});
    } else {
      liney.push_back({a, c, b});
    }
  }
  sort(vx.begin(), vx.end());
  sort(vy.begin(), vy.end());
  vx.resize(unique(vx.begin(), vx.end()) - vx.begin());
  vy.resize(unique(vy.begin(), vy.end()) - vy.begin());
  for (auto &i : linex) {
    i.s = (int)(lower_bound(vy.begin(), vy.end(), i.s) - vy.begin());
    i.e = (int)(lower_bound(vy.begin(), vy.end(), i.e) - vy.begin());
    i.x = (int)(lower_bound(vx.begin(), vx.end(), i.x) - vx.begin());
  }
  for (auto &i : liney) {
    i.s = (int)(lower_bound(vx.begin(), vx.end(), i.s) - vx.begin());
    i.e = (int)(lower_bound(vx.begin(), vx.end(), i.e) - vx.begin());
    i.x = (int)(lower_bound(vy.begin(), vy.end(), i.x) - vy.begin());
  }
  sort(linex.begin(), linex.end(), cmp);
  sort(liney.begin(), liney.end(), cmp);
  printf("%lld\\n", edge() - vertex() + component());
}