洛谷P4097 【模板】李超线段树 / [HEOI2013] Segment 题解 李超线段树 模板题
题目链接:https://www.luogu.com.cn/problem/P4097
解题思路:完全来自 oi.wiki
双倍经验:P4254 [JSOI2008] Blue Mary 开公司(更简单,因为每次更新都是整个区间)
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5, mod = 39989;
const double eps = 1e-9;
// x>y:返回1; x<y:返回-1; x=y:返回0
int cmp(double x, double y) {
if (x - y > eps) return 1;
if (y - x > eps) return -1;
return 0;
}
struct Line {
double k, b; // y=kx+b
} line[maxn];
int n, idx, lastans;
int trans(int x, int m = mod) {
return (x + lastans - 1) % m + 1;
}
void new_line(int x0, int y0, int x1, int y1) {
if (x0 == x1) {
line[++idx] = {0, 1.0 * max(y0, y1)};
}
else {
double k = 1.0 * (y1 - y0) / (x1 - x0);
double b = y0 - k * x0;
line[++idx] = {k, b};
}
}
// 返回第 p 条线段在横坐标为 x 时对应的纵坐标 y
double get_y(int p, int x) {
return line[p].k * x + line[p].b;
}
int tr[(mod+5)<<2];
#define lson l, mid, u<<1
#define rson mid+1, r, u<<1|1
void upd(int p, int l, int r, int u) {
int &q = tr[u], mid = l + r >> 1;
int c_mid = cmp(get_y(p, mid), get_y(q, mid));
if (c_mid == 1 || !c_mid && p < q) swap(p, q);
int c_l = cmp(get_y(p, l), get_y(q, l)), c_r = cmp(get_y(p, r), get_y(q, r));
if (c_l == 1 || !c_l && p < q) upd(p, lson);
if (c_r == 1 || !c_r && p < q) upd(p, rson);
}
void update(int p, int L, int R, int l, int r, int u) {
if (L <= l && r <= R) {
upd(p, l, r, u);
return;
}
int mid = l + r >> 1;
if (L <= mid) update(p, L, R, lson);
if (R > mid) update(p, L, R, rson);
}
pair<int, double> query(int x, int l, int r, int u) {
int p = tr[u];
double ans = get_y(p, x);
if (l == r)
return {p, ans};
int mid = l + r >> 1;
auto [q, tmp] = (x <= mid) ? query(x, lson) : query(x, rson);
int c_mid = cmp(tmp, ans);
if (c_mid == 1 || !c_mid && q < p) {
p = q;
ans = tmp;
}
return { p, ans };
}
int main() {
scanf("%d", &n);
while (n--) {
int op;
scanf("%d", &op);
if (op == 0) {
long long x, k;
scanf("%lld", &k);
x = trans(k);
lastans = query(x, 1, mod, 1).first;
printf("%d\n", lastans);
}
else { // op == 1
long long x0, y0, x1, y1;
scanf("%lld%lld%lld%lld", &x0, &y0, &x1, &y1);
x0 = trans(x0);
y0 = trans(y0, 1e9);
x1 = trans(x1);
y1 = trans(y1, 1e9);
if (x0 > x1) {
swap(x0, x1);
swap(y0, y1);
}
new_line(x0, y0, x1, y1);
update(idx, x0, x1, 1, mod, 1);
}
}
return 0;
}
浙公网安备 33010602011771号