[BZOJ3165][Heoi2013]Segment(线段树)

Address

https://www.lydsy.com/JudgeOnline/problem.php?id=3165

Solution

和 BZOJ 1568 / JSOI 2008 Blue Mary 开公司那题一样。
只不过那题是整体加线段,此题是区间加线段。
把一个区间在线段树上拆成 log 39989 个区间后,对每个拆出的区间插入线段。
区间插入线段的「李超线段树」详解:
https://blog.csdn.net/xyz32768/article/details/81286205
注意对斜率不存在的线段特殊处理。
复杂度 O ( n log 2 39989 )

Code

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define p2 p << 1
#define p3 p << 1 | 1
using namespace std;
inline int read() {
    int res = 0; bool bo = 0; char c;
    while (((c = getchar()) < '0' || c > '9') && c != '-');
    if (c == '-') bo = 1; else res = c - 48;
    while ((c = getchar()) >= '0' && c <= '9')
        res = (res << 3) + (res << 1) + (c - 48);
    return bo ? ~res + 1 : res;
}
const int N = 16e4 + 5;
int n, id[N];
double sty[N], edy[N];
struct node {int i; double pos;};
void addline(int l, int r, double yl, double yr, int i, int p) {
    if (!id[p]) return (void) (id[p] = i, sty[p] = yl, edy[p] = yr);
    if (l == r) {
        if (yl > sty[p] || (yl == sty[p] && i < id[p]))
            id[p] = i, sty[p] = edy[p] = yl;
        return;
    }
    if ((yl < sty[p] && yr < edy[p]) || (yl <= sty[p] &&
        yr <= edy[p] && i > id[p]))
            return;
    if ((yl > sty[p] && yr > edy[p]) || (yl >= sty[p] &&
        yr >= edy[p] && i < id[p]))
        return (void) (id[p] = i, sty[p] = yl, edy[p] = yr);
    int mid = l + r >> 1;
    double k1 = (yr - yl) / (r - l), k2 = (edy[p] - sty[p]) / (r - l);
    double b1 = yl - k1 * l, b2 = sty[p] - k2 * l, x;
    x = (b1 - b2) / (k2 - k1);
    if ((x <= mid) ^ (yl > sty[p])) swap(yl, sty[p]), swap(yr, edy[p]),
        swap(i, id[p]);
    double midy = yl + (yr - yl) * (1.0 * (mid - l) / (r - l)),
        dimy = yl + (yr - yl) * (1.0 * (mid + 1 - l) / (r - l));
    if (x <= mid) addline(l, mid, yl, midy, i, p2);
    else addline(mid + 1, r, dimy, yr, i, p3);
}
void change(int l, int r, int s, int e,
double yl, double yr, int i, int p) {
    if (l == s && r == e) return addline(l, r, yl, yr, i, p);
    int mid = l + r >> 1;
    if (e <= mid) change(l, mid, s, e, yl, yr, i, p2);
    else if (s >= mid + 1) change(mid + 1, r, s, e, yl, yr, i, p3);
    else {
        double midy = yl + (yr - yl) * (1.0 * (mid - s) / (e - s)),
            dimy = yl + (yr - yl) * (1.0 * (mid + 1 - s) / (e - s));
        change(l, mid, s, mid, yl, midy, i, p2);
        change(mid + 1, r, mid + 1, e, dimy, yr, i, p3);
    }
}
void change2(int l, int r, int pos, double y, int i, int p) {
    if (l == r) {
        if (y > sty[p] || (y == sty[p] && i < id[p]))
            id[p] = i, sty[p] = edy[p] = y;
        return;
    }
    int mid = l + r >> 1;
    if (pos <= mid) change2(l, mid, pos, y, i, p2);
    else change2(mid + 1, r, pos, y, i, p3);
}
node ask(int l, int r, int pos, int p) {
    if (l == r) return id[p] ? (node) {id[p], sty[p]} : (node) {0, 0};
    int mid = l + r >> 1; node res;
    if (pos <= mid) res = ask(l, mid, pos, p2);
    else res = ask(mid + 1, r, pos, p3);
    double val = sty[p] + (edy[p] - sty[p]) * (1.0 * (pos - l) / (r - l));
    if (!res.i || (val > res.pos || (val == res.pos && id[p] < res.i)))
        res.i = id[p], res.pos = val;
    return res;
}
int main() {
    int op, x0, y0, x1, y1, lst = 0, T = 0;
    n = read(); while (n--) {
        op = read();
        if (op) {
            x0 = (read() + lst - 1) % 39989 + 1;
            y0 = (read() + lst - 1) % 1000000000 + 1;
            x1 = (read() + lst - 1) % 39989 + 1;
            y1 = (read() + lst - 1) % 1000000000 + 1;
            T++;
            if (x0 > x1) swap(x0, x1), swap(y0, y1);
            if (x0 == x1) change2(1, 39989, x0, max(y0, y1), T, 1);
            else change(1, 39989, x0, x1, y0, y1, T, 1);
        }
        else {
            x1 = (read() + lst - 1) % 39989 + 1;
            printf("%d\n", lst = ask(1, 39989, x1, 1).i);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xyz32768/article/details/81286322