光线追踪

#include<cstdio>
#include<cstring>
#include<algorithm>

struct Node {
  int ope;
  int x[2];
  int y[2];
} node[100005];

double ac[300005];
int cnt = 0;

int tree[300005 << 2][2];
int ans[300005 << 2][2];

double at(double y, double x) {
  if(x == 0) return 0x7fffffff;
  return y / x;
}

void add(int now, int l, int r, int al, int ar, int val, int id, int side) {
  if(l == al && r == ar) {
    if(tree[now][side] >= val) {
      tree[now][side] = val;
      ans[now][side] = id;
    }
    return;
  }
  const int MID = (l + r) >> 1;
  if(ar <= MID) {
    add(now << 1, l, MID, al, ar, val, id, side);
  } else if(al > MID) {
    add(now << 1 | 1, MID + 1, r, al, ar, val, id, side);
  } else {
    add(now << 1, l, MID, al, MID, val, id, side);
    add(now << 1 | 1, MID + 1, r, MID + 1, ar, val, id, side);
  }
  return;
}

void ask(int now, int loc, int l, int r, int &ansx, int &ansy, int &xid, int &yid) {
  if(tree[now][0] < ansx) {
    ansx = tree[now][0];
    xid = ans[now][0];
  }
  if(tree[now][0] == ansx) {
    xid = std::max(xid, ans[now][0]);
  }
  if(tree[now][1] < ansy) {
    ansy = tree[now][1];
    yid = ans[now][1];
  }
  if(tree[now][1] == ansy) {
    yid = std::max(yid, ans[now][1]);
  }
  if(l == r) return;
  const int MID = (l + r) >> 1;
  if(loc <= MID) {
    ask(now << 1, loc, l, MID, ansx, ansy, xid, yid);
  } else {
    ask(now << 1 | 1, loc, MID + 1, r, ansx, ansy, xid, yid);
  }
  return;
}

int main() {
  int open;
  scanf("%d", &open); 
  for(int i = 1; i <= open; ++i) {
    scanf("%d", &node[i].ope);
    switch(node[i].ope) {
      case 1: {
        scanf("%d%d%d%d", &node[i].x[0], &node[i].y[0], &node[i].x[1], &node[i].y[1]);
        ac[++cnt] = at(node[i].y[0], node[i].x[0]);
    // printf("%lf\n", ac[cnt]);
        ac[++cnt] = at(node[i].y[1], node[i].x[0]);
    // printf("%lf\n", ac[cnt]);
        ac[++cnt] = at(node[i].y[0], node[i].x[1]);
    // printf("%lf\n", ac[cnt]);
        break;
      }
      case 2: {
        scanf("%d%d", &node[i].x[0], &node[i].y[0]);
        ac[++cnt] = at(node[i].y[0], node[i].x[0]);
    // printf("%lf\n", ac[cnt]);
        break;
      }
    }
  }
  std::sort(ac + 1, ac + 1 + cnt);
  // for(int i = 1; i <= cnt; ++i) {
  //   printf("%lf\n", ac[i]);
  // }
  memset(tree, 0x7f, sizeof(tree));
  for(int i = 1; i <= open; ++i) { 
    switch(node[i].ope) {
      case 1: {
        int li = std::lower_bound(ac + 1, ac + 1 + cnt, at(node[i].y[0], node[i].x[0])) - ac;
        int ri = std::lower_bound(ac + 1, ac + 1 + cnt, at(node[i].y[1], node[i].x[0])) - ac;
        add(1, 1, cnt, li, ri, node[i].x[0], i, 0);
        ri = li;
        li = std::lower_bound(ac + 1, ac + 1 + cnt, at(node[i].y[0], node[i].x[1])) - ac;
        add(1, 1, cnt, li, ri, node[i].y[0], i, 1);
        break;
      }
      case 2: {
        int x = node[i].x[0];
        int y = node[i].y[0];
        double k = at(y, x);
        int loc = std::lower_bound(ac + 1, ac + 1 + cnt, k) - ac;
        int ansx = 0x7fffffff;
        int xid = 0;
        int ansy = 0x7fffffff;
        int yid = 0;
        ask(1, loc, 1, cnt, ansx, ansy, xid, yid);
        if(!xid || !yid) {
          printf("%d\n", xid + yid);
        } else {
          if(k == 0x7fffffff) {
            if(node[xid].y[0] < node[yid].y[0]) {
              printf("%d\n", xid);
            } else if(node[yid].y[0] < node[xid].y[0]) {
              printf("%d\n", yid);
            } else {
              printf("%d\n", std::max(xid, yid));
            }
          } else if(k == 0) {
            if(node[xid].x[0] < node[yid].x[0]) {
              printf("%d\n", xid);
            } else if(node[yid].x[0] < node[xid].x[0]) {
              printf("%d\n", yid);
            } else {
              printf("%d\n", std::max(xid, yid));
            }
          } else {
            if(ansx * k == ansy) {
              printf("%d\n", std::max(xid, yid));
            }
            if(ansx * k < ansy) {
              printf("%d\n", xid);
            }
            if(ansx * k > ansy) {
              printf("%d\n", yid);
            }
          }
        }
        break;
      }
    }
  }
  return 0;
}