bzoj1935 [SHOI2007]Tree 园丁的烦恼

Posted juanzhang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1935 [SHOI2007]Tree 园丁的烦恼相关的知识,希望对你有一定的参考价值。

\(\verb|bzoj1935 [SHOI2007]Tree 园丁的烦恼|\)

静态询问平面点数

\(x_i,\ y_i\in[0,\ 10^7],\ n,\ m\leq5\times10^5\)

二维偏序,cdq分治


可以直接 cdq分治,也可以离散化后用 BIT 做、、注意排序时若 \(x,\ y\) 相同,要将点放在询问前面

时间复杂度 \(O(n\log n)\)

代码

cdq分治

#include <bits/stdc++.h>
using namespace std;

#define nc getchar()
const int maxn = 5e5 + 10;
int n, m, len, ans[maxn];

struct node {
  int x, y, val, tid;
  node(int _x = 0, int _y = 0, int _v = 0, int _t = 0) :
    x(_x), y(_y), val(_v), tid(_t) {}
  bool operator < (const node& o) const {
    return x == o.x ? y == o.y ? !val : y < o.y : x < o.x;
  }
} a[maxn * 5], b[maxn * 5];

inline int read() {
  int x = 0;
  char c = nc;
  while (c < 48) c = nc;
  while (c > 47) x = x * 10 + c - 48, c = nc;
  return x;
}

void cdq(int l, int r) {
  if (l == r) return;
  int mid = (l + r) >> 1;
  cdq(l, mid), cdq(mid + 1, r);
  for (int p = l, p1 = l, p2 = mid + 1, s = 0; p <= r; p++) {
    if (p2 > r || (p1 <= mid && a[p1].y <= a[p2].y)) {
      s += !a[p1].val, b[p] = a[p1++];
    } else {
      ans[a[p2].tid] += a[p2].val * s, b[p] = a[p2++];
    }
  }
  for (int i = l; i <= r; i++) {
    a[i] = b[i];
  }
}

int main() {
  n = read(), m = read();
  for (int i = 1; i <= n; i++) {
    a[i].x = read(), a[i].y = read();
  }
  len = n;
  for (int i = 1; i <= m; i++) {
    int x1 = read(), y1 = read();
    int x2 = read(), y2 = read();
    a[++len] = node(x2, y2, 1, i);
    a[++len] = node(x1 - 1, y2, -1, i);
    a[++len] = node(x2, y1 - 1, -1, i);
    a[++len] = node(x1 - 1, y1 - 1, 1, i);
  }
  sort(a + 1, a + len + 1), cdq(1, len);
  for (int i = 1; i <= m; i++) {
    printf("%d\n", ans[i]);
  }
  return 0;
}

BIT

#include <bits/stdc++.h>
using namespace std;

#define nc getchar()
#define get_val(x) (lower_bound(data + 1, data + tot + 1, x) - data)
const int maxn = 5e5 + 10;
int n, m, len, tot, ans[maxn], data[maxn * 5], c[maxn * 5];

struct Query {
  int x, y, val, tid;
  Query(int _x = 0, int _y = 0, int _v = 0, int _t = 0) :
    x(_x), y(_y), val(_v), tid(_t) {}
  inline bool operator < (const Query& o) const {
    return x == o.x ? y == o.y ? !val : y < o.y : x < o.x;
  }
} Q[maxn * 5];

inline int read() {
  int x = 0;
  char c = nc;
  while (c < 48) c = nc;
  while (c > 47) x = (x << 3) + (x << 1) + (c ^ 48), c = nc;
  return x;
}

inline void add(int pos) {
  for (; pos <= tot; pos += pos & -pos) {
    c[pos]++;
  }
}

inline int query(int pos) {
  int res = 0;
  for (; pos; pos &= pos - 1) {
    res += c[pos];
  }
  return res;
}

int main() {
  n = read(), m = read();
  for (int i = 1; i <= n; i++) {
    data[++tot] = Q[i].x = read();
    data[++tot] = Q[i].y = read();
  }
  len = n;
  for (int i = 1; i <= m; i++) {
    int x1 = read(), y1 = read();
    int x2 = read(), y2 = read();
    if (x1) data[++tot] = x1 - 1;
    if (y1) data[++tot] = y1 - 1;
    data[++tot] = x2, data[++tot] = y2;
    Q[++len] = Query(x2, y2, 1, i);
    if (x1) Q[++len] = Query(x1 - 1, y2, -1, i);
    if (y1) Q[++len] = Query(x2, y1 - 1, -1, i);
    if (x1 && y1) Q[++len] = Query(x1 - 1, y1 - 1, 1, i);
  }
  sort(data + 1, data + tot + 1);
  tot = unique(data + 1, data + tot + 1) - data - 1;
  for (int i = 1; i <= len; i++) {
    Q[i].x = get_val(Q[i].x);
    Q[i].y = get_val(Q[i].y);
  }
  sort(Q + 1, Q + len + 1);
  for (int i = 1; i <= len; i++) {
    if (Q[i].val) {
      ans[Q[i].tid] += Q[i].val * query(Q[i].y);
    } else {
      add(Q[i].y);
    }
  }
  for (int i = 1; i <= m; i++) {
    printf("%d\n", ans[i]);
  }
  return 0;
}

以上是关于bzoj1935 [SHOI2007]Tree 园丁的烦恼的主要内容,如果未能解决你的问题,请参考以下文章

[bzoj1935][Shoi2007]Tree 园丁的烦恼 _树状数组

BZOJ1935: [Shoi2007]Tree 园丁的烦恼

bzoj千题计划143:bzoj1935: [Shoi2007]Tree 园丁的烦恼

bzoj1935: [Shoi2007]Tree 园丁的烦恼

BZOJ 1935: [Shoi2007]Tree 园丁的烦恼 [树状数组 离线 离散化]

BZOJ.1935.[SHOI2007]Tree园丁的烦恼(CDQ分治 三维偏序)