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

#include <algorithm>
#include <cstdio>
#include <vector>

using namespace std;

class Node {
public:
  int location; // 要素全体の位置 ( 昇順に並べた時 )
  int p, l, r;
  // コンストラクタ
  Node() {}
};

class Point {
public:
  int id, x, y;

  Point() {}
  // メンバ変数の初期化
  Point(int id, int x, int y) : id(id), x(x), y(y) {}

  // 演算子のオーバーロード ( constメンバ関数 : メンバ変数の変更を禁止する)
  // main() 内の sort() で使用する
  bool operator<(const Point &p) const { return id < p.id; }

  void print() {
    // cout より高速な　printf 関数を使用
    printf("%d\\n", id);
  }
};

static const int MAX = 1000000;
static const int NIL = -1;

int N;
Point P[MAX];
Node T[MAX];
int np;

// makeKDTree() 内の sort()のための比較関数
bool lessX(const Point &p1, const Point &p2) { return p1.x < p2.x; }
bool lessY(const Point &p1, const Point &p2) { return p1.y < p2.y; }

// ２分木を作成する関数
int makeKDTree(int l, int r, int depth) {
  if (!(l < r)) {
    return NIL;
  }

  // 中央値の演算
  int mid = (l + r) / 2;
  // ノードNo.
  int t = np++;

  // 木の深さによって、ソートする軸を変更する
  if (depth % 2 == 0) {
    // Xの要素について昇順にソートする
    // lessX : 比較関数
    sort(P + l, P + r, lessX);
  } else {
    // Yの要素について昇順にソートする
    // lessY : 比較関数
    sort(P + l, P + r, lessY);
  }

  // 要素全体における位置
  T[t].location = mid;
  // 左部分木の作成
  T[t].l = makeKDTree(l, mid, depth + 1);
  // 右部分木の作成
  T[t].r = makeKDTree(mid + 1, r, depth + 1);

  return t;
}

// 要素を検索するための関数
// v      : 根の要素No.
// sx〜ty : 検索する範囲
// depth  : 木の深さ
// 　ans   : 条件に合う要素を格納するvector
void find(int v, int sx, int tx, int sy, int ty, int depth,
          vector<Point> &ans) {
  int x = P[T[v].location].x;
  int y = P[T[v].location].y;

  if (sx <= x && x <= tx && sy <= y && y <= ty) {
    // 条件を満たす点が見つかった
    ans.push_back(P[T[v].location]);
  }

  if (depth % 2 == 0) {
    // -----------------
    // 木の深さが偶数の時
    // -----------------
    if (T[v].l != NIL) {
      if (sx <= x) {
        // 左部分木を探索
        find(T[v].l, sx, tx, sy, ty, depth + 1, ans);
      }
    }

    if (T[v].r != NIL) {
      if (x <= tx) {
        // 右部分木を探索
        find(T[v].r, sx, tx, sy, ty, depth + 1, ans);
      }
    }
  } else {
    // -----------------
    // 木の深さが奇数の時
    // -----------------
    if (T[v].l != NIL) {
      if (sy <= y) {
        // 左部分木を探索
        find(T[v].l, sx, tx, sy, ty, depth + 1, ans);
      }
    }

    if (T[v].r != NIL) {
      if (y <= ty) {
        // 右部分木を探索
        find(T[v].r, sx, tx, sy, ty, depth + 1, ans);
      }
    }
  }

  return;
}

// メイン関数
int main(void) {
  int x, y;

  scanf("%d", &N);

  for (int i = 0; i < N; i++) {
    // cin より高速な scanf 関数を使用
    scanf("%d %d", &x, &y);
    // 各要素の設定
    P[i] = Point(i, x, y);
    T[i].l = T[i].r = T[i].p = NIL;
  }

  np = 0;

  // 2分探索木の作成
  int root = makeKDTree(0, N, 0);

  int q;
  scanf("%d", &q);
  int sx, tx, sy, ty;
  vector<Point> ans;

  for (int i = 0; i < q; i++) {
    scanf("%d %d %d %d", &sx, &tx, &sy, &ty);
    // vector要素の初期化
    ans.clear();
    // 要素の検索
    find(root, sx, tx, sy, ty, 0, ans);
    // 見つかった結果を id の昇順にソートする
    sort(ans.begin(), ans.end());

    for (int j = 0; j < ans.size(); j++) {
      // 結果の表示
      ans[j].print();
    }

    printf("\\n");
  }

  return 0;
}


Error: TLE

Fixed submission:

// 領域探索
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <stack>
#include <vector>

#include <queue>

using namespace std;

// x, yの値を保持する構造体
typedef struct {
  int x;
  int y;
} X_Y_DATA;

// x, yの値の範囲を保持する構造体
typedef struct {
  int x_start;
  int x_end;

  int y_start;
  int y_end;
} X_Y_RANGE;

int main(void) {
  int n, q;

  X_Y_DATA xy_data;
  X_Y_RANGE xy_range;

  vector<X_Y_DATA> v_xy_Data;
  vector<X_Y_RANGE> v_xy_Range;

  cin >> n;

  for (int i = 0; i < n; i++) {
    // x, yの値の組を設定
    cin >> xy_data.x >> xy_data.y;
    v_xy_Data.push_back(xy_data);
  }

  cin >> q;

  for (int i = 0; i < q; i++) {
    // x, yの値の範囲を設定
    cin >> xy_range.x_start >> xy_range.x_end >> xy_range.y_start >>
        xy_range.y_end;

    v_xy_Range.push_back(xy_range);
  }

  for (int i = 0; i < v_xy_Range.size(); i++) {
    for (int j = 0; j < v_xy_Data.size(); j++) {
      // 各点が条件を満たしているかを順番に確認する
      if (v_xy_Range[i].x_start <= v_xy_Data[j].x &&
          v_xy_Data[j].x <= v_xy_Range[i].x_end) {
        if (v_xy_Range[i].y_start <= v_xy_Data[j].y &&
            v_xy_Data[j].y <= v_xy_Range[i].y_end) {
          printf("%d\\n", j);
        }
      }
    }

    printf("\\n");
  }

  return 0;
}