题目大意:
要求在平面直角坐标系下维护两个操作:
1.在平面上加入一条线段。记第i条被插入的线段的标号为i。
2.给定一个数k,询问与直线 x = k相交的线段中,交点最靠上的线段的编号
AC代码:
#include <iostream>
#include <cstring>
#define mod1 39989
#define mod2 1000000000
#define endl '\n'
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define ls(rt) rt << 1
#define rs(rt) rt << 1 | 1
using namespace std;
typedef pair <double, int> pdi;
const int maxn = 2e5 + 10;
int cnt = 0;
struct L {
double k, b;
} line[maxn];
struct segtree {
int id, l, r;
} sgt[maxn << 1];
int sgt_cnt = 0;
double cal(int id, int x) {return line[id].k * x + line[id].b;}
void add(int x1, int y1, int x2, int y2) {
if (x1 == x2) line[++cnt].k = 0, line[cnt].b = max(y1, y2);
else line[++cnt].k = 1.0 * (y1 - y2) / (x1 - x2), line[cnt].b = y1 - line[cnt].k * x1;
}
void update(int lc, int rc, int &rt, int l, int r, int u) {
if (!rt) rt = ++sgt_cnt;
int mi = (lc + rc) >> 1;
if (r < lc || l > rc) return;
/*if (lc == rc) {
sgt[rt] = u;
return;
}*/ //这里应该要判断是否在范围内先
int v = sgt[rt].id;
double resu = cal(u, mi), resv = cal(sgt[rt].id, mi);
if (l <= lc && rc <= r) {
if (lc == rc) {
if (resu > resv) sgt[rt].id = u;
return;
}
if (line[u].k > line[v].k) {
if (resu > resv) {
sgt[rt].id = u;
//update(lc, mi, ls(rt), l, r, u);
update(lc, mi, sgt[rt].l, l, r, v);
//运用到可持久化标记的思想,所以u的标记并没有下传,只要询问时统计一遍路径上的点即可
//或者可以这样想,如果在[lc,mi]区间v比u更优,但是没有拿v来更新,所以就统计不到v,此时就要传v下去更新
}
else
update(mi + 1, rc, sgt[rt].r, l, r, u);
}
else if (line[u].k < line[v].k) {
if (resu > resv) {
sgt[rt].id = u;
//update(mi + 1, rc, rs(rt), l, r, u);
update(mi + 1, rc, sgt[rt].r, l , r, v);
}
else
update(lc, mi, sgt[rt].l, l, r, u);
}
else {
if (line[u].b > line[v].b)
sgt[rt].id = u;
}
return;
}
update(lc, mi, sgt[rt].l, l, r, u);
update(mi + 1, rc, sgt[rt].r, l, r, u);
}
pdi pmax(pdi A, pdi B) {
if (A.first > B.first) return A;
else if (A.first < B.first) return B;
else if (A.second < B.second) return A;
else return B;
}
pdi query(int l, int r, int rt, int k) {
if (r < k || k < l) return {0, 0};
int mi = (l + r) >> 1;
double res = cal(sgt[rt].id, k);
if (l == r) return {res, sgt[rt].id};
return pmax({res, sgt[rt].id}, pmax(query(l, mi, sgt[rt].l, k), query(mi + 1, r, sgt[rt].r, k)));
}
int n, op, k, x1, x2, y1, y2, x, lastans = 0, rt = 0;
int main() {
IOS;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> op;
if (!op) {
cin >> k;
x = (k + lastans - 1) % mod1 + 1;
cout << (lastans = query(1, mod1, 1, x).second) << endl;
}
else {
cin >> x1 >> y1 >> x2 >> y2;
x1 = (x1 + lastans - 1) % mod1 + 1,
y1 = (y1 + lastans - 1) % mod2 + 1,
x2 = (x2 + lastans - 1) % mod1 + 1,
y2 = (y2 + lastans - 1) % mod2 + 1;
if (x1 > x2) swap(x1, x2), swap(y1, y2);
add(x1, y1, x2, y2);
update(1, mod1, rt, x1, x2, cnt);
}
}
}