Description:
要求在平面直角坐标系下维护两个操作:
1.
1.
在平面上加入一条线段。记第
i
i
条被插入的线段的标号为。
2.
2.
给定一个数
k
k
,询问与直线相交的线段中,交点最靠上的线段的编号。
Solution:
对于每个区间
[l,r]
[
l
,
r
]
,我们维护一条线段
a
a
。这条线段是这个区间中与和
x=r
x
=
r
交点最靠上的线段。
每次加入一条新的线段就把线段对应到线段树对应的区间,然后和已有的线段比较高低,把较低的向对应的区间重新更新即可,复杂度
O(nlog2n)
O
(
n
l
o
g
2
n
)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 4e4 + 5;
struct Seg {
double x, y, k, b;
int id;
double c(double p) {
return k * p + b;
}
} seg[maxn * 4];
int n, m, id, ans;
double mx;
int read() {
int x = 0, f = 1;
char c = getchar();
while(!isdigit(c)) {
if(c == '-') {
f = -1;
}
c = getchar();
}
while(isdigit(c)) {
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
void pushdown(int l, int r, int x, int a, int b, Seg t) {
double A1 = seg[x].c(l), A2 = t.c(l), B1 = seg[x].c(r), B2 = t.c(r);
if((A1 < A2 && B1 < B2) || !seg[x].id) {
seg[x] = t;
return;
}
if(A1 > A2 && B1 > B2) {
return;
}
if(l == r) {
return;
}
int mid = (l + r) >> 1;
double c = (seg[x].b - t.b) / (t.k- seg[x].k);
if(c <= mid) {
if(A1 < A2) {
pushdown(l, mid, x << 1, a, b, t);
} else {
pushdown(l, mid, x << 1, a, b, seg[x]);
seg[x] = t;
}
} else {
if(B1 < B2) {
pushdown(mid + 1, r, x << 1 | 1, a, b, t);
} else {
pushdown(mid + 1, r, x << 1 | 1, a, b, seg[x]);
seg[x] = t;
}
}
}
void update(int l, int r, int x, int a, int b, Seg t) {
if(l > b || r < a) {
return;
}
if(l >= a && r <= b) {
pushdown(l, r, x, a, b, t);
return;
}
int mid = (l + r) >> 1;
update(l, mid, x << 1, a, b, t);
update(mid + 1, r, x << 1 | 1, a, b, t);
}
void query(int l, int r, int x, int p) {
if(seg[x].id) {
double tmp = seg[x].c(p);
if(tmp > mx) {
mx = tmp;
ans = seg[x].id;
} else if(tmp == mx) {
ans = min(ans, seg[x].id);
}
}
if(l == r) {
return;
}
int mid = (l + r) >> 1;
if(p <= mid) {
query(l, mid, x << 1, p);
} else {
query(mid + 1, r, x << 1 | 1, p);
}
}
int main() {
m = read();
n = maxn - 1;
while(m--) {
int opt = read();
if(opt == 0) {
int k = (read() + ans - 1) % 39989 + 1;
mx = -1e18;
ans = 0;
query(1, n, 1, k);
printf("%d\n", ans);
} else {
double x0 = (read() + ans - 1) % 39989 + 1, y0 = (read() + ans - 1) % (int)(1e9) + 1, x1 = (read() + ans - 1) % 39989 + 1, y1 = (read() + ans - 1) % (int)(1e9) + 1;
if(x0 > x1) {
swap(x0, x1);
swap(y0, y1);
}
double K = x0 == x1 ? 0 : (y1 - y0) / (x1 - x0), B = y0 - K * x0;
update(1, n, 1, x0, x1, (Seg){x0, y0, K, B, ++id});
}
}
return 0;
}